]> matita.cs.unibo.it Git - helm.git/commitdiff
Broken libs moved to broken_lib
authorClaudio Sacerdoti Coen <claudio.sacerdoticoen@unibo.it>
Wed, 26 Dec 2018 15:09:34 +0000 (16:09 +0100)
committerClaudio Sacerdoti Coen <claudio.sacerdoticoen@unibo.it>
Fri, 27 Sep 2019 13:45:22 +0000 (15:45 +0200)
Some can probably be restored with some love.

34 files changed:
matita/matita/broken_lib/binding/db.ma [new file with mode: 0644]
matita/matita/broken_lib/binding/fp.ma [new file with mode: 0644]
matita/matita/broken_lib/binding/ln.ma [new file with mode: 0644]
matita/matita/broken_lib/binding/ln_concrete.ma [new file with mode: 0644]
matita/matita/broken_lib/binding/names.ma [new file with mode: 0644]
matita/matita/broken_lib/finite_lambda/confluence.ma [new file with mode: 0644]
matita/matita/broken_lib/finite_lambda/reduction.ma [new file with mode: 0644]
matita/matita/broken_lib/finite_lambda/terms_and_types.ma [new file with mode: 0644]
matita/matita/broken_lib/finite_lambda/typing.ma [new file with mode: 0644]
matita/matita/broken_lib/reverse_complexity/big_O.ma [new file with mode: 0644]
matita/matita/broken_lib/reverse_complexity/gap.ma [new file with mode: 0644]
matita/matita/broken_lib/reverse_complexity/hierarchy.ma [new file with mode: 0644]
matita/matita/broken_lib/reverse_complexity/speed_clean.ma [new file with mode: 0644]
matita/matita/broken_lib/reverse_complexity/speed_def.ma [new file with mode: 0644]
matita/matita/broken_lib/reverse_complexity/speed_new.ma [new file with mode: 0644]
matita/matita/broken_lib/reverse_complexity/toolkit.ma [new file with mode: 0644]
matita/matita/broken_lib/turing/multi_to_mono/multi_to_mono.ma [new file with mode: 0644]
matita/matita/lib/binding/db.ma [deleted file]
matita/matita/lib/binding/fp.ma [deleted file]
matita/matita/lib/binding/ln.ma [deleted file]
matita/matita/lib/binding/ln_concrete.ma [deleted file]
matita/matita/lib/binding/names.ma [deleted file]
matita/matita/lib/finite_lambda/confluence.ma [deleted file]
matita/matita/lib/finite_lambda/reduction.ma [deleted file]
matita/matita/lib/finite_lambda/terms_and_types.ma [deleted file]
matita/matita/lib/finite_lambda/typing.ma [deleted file]
matita/matita/lib/reverse_complexity/big_O.ma [deleted file]
matita/matita/lib/reverse_complexity/gap.ma [deleted file]
matita/matita/lib/reverse_complexity/hierarchy.ma [deleted file]
matita/matita/lib/reverse_complexity/speed_clean.ma [deleted file]
matita/matita/lib/reverse_complexity/speed_def.ma [deleted file]
matita/matita/lib/reverse_complexity/speed_new.ma [deleted file]
matita/matita/lib/reverse_complexity/toolkit.ma [deleted file]
matita/matita/lib/turing/multi_to_mono/multi_to_mono.ma [deleted file]

diff --git a/matita/matita/broken_lib/binding/db.ma b/matita/matita/broken_lib/binding/db.ma
new file mode 100644 (file)
index 0000000..534874f
--- /dev/null
@@ -0,0 +1,110 @@
+(**************************************************************************)
+(*       ___                                                              *)
+(*      ||M||                                                             *)
+(*      ||A||       A project by Andrea Asperti                           *)
+(*      ||T||                                                             *)
+(*      ||I||       Developers:                                           *)
+(*      ||T||         The HELM team.                                      *)
+(*      ||A||         http://helm.cs.unibo.it                             *)
+(*      \   /                                                             *)
+(*       \ /        This file is distributed under the terms of the       *)
+(*        v         GNU General Public License Version 2                  *)
+(*                                                                        *)
+(**************************************************************************)
+
+include "basics/lists/list.ma".
+
+axiom alpha : Type[0].
+notation "𝔸" non associative with precedence 90 for @{'alphabet}.
+interpretation "set of names" 'alphabet = alpha.
+
+inductive tp : Type[0] β‰ 
+| top : tp
+| arr : tp β†’ tp β†’ tp.
+inductive tm : Type[0] β‰ 
+| var : nat β†’ tm
+| par :  π”Έ β†’ tm
+| abs : tp β†’ tm β†’ tm
+| app : tm β†’ tm β†’ tm.
+
+let rec Nth T n (l:list T) on n β‰ 
+  match l with 
+  [ nil β‡’ None ?
+  | cons hd tl β‡’ match n with
+    [ O β‡’ Some ? hd
+    | S n0 β‡’ Nth T n0 tl ] ].
+
+inductive judg : list tp β†’ tm β†’ tp β†’ Prop β‰ 
+| t_var : βˆ€g,n,t.Nth ? n g = Some ? t β†’ judg g (var n) t
+| t_app : βˆ€g,m,n,t,u.judg g m (arr t u) β†’ judg g n t β†’ judg g (app m n) u
+| t_abs : βˆ€g,t,m,u.judg (t::g) m u β†’ judg g (abs t m) (arr t u).
+
+definition Env := list (𝔸 Γ— tp).
+
+axiom vclose_env : Env β†’ list tp.
+axiom vclose_tm : Env β†’ tm β†’ tm.
+axiom Lam : π”Έ β†’ tp β†’ tm β†’ tm.
+definition Judg β‰ Ξ»G,M,T.judg (vclose_env G) (vclose_tm G M) T.
+definition dom β‰ Ξ»G:Env.map ?? (fst ??) G.
+
+definition sctx β‰ π”Έ Γ— tm.
+axiom swap_tm : π”Έ β†’ π”Έ β†’ tm β†’ tm.
+definition sctx_app : sctx β†’ π”Έ β†’ tm β‰ Ξ»M0,Y.let βŒ©X,MβŒͺ β‰ M0 in swap_tm X Y M.
+
+axiom in_list : βˆ€A:Type[0].A β†’ list A β†’ Prop.
+interpretation "list membership" 'mem x l = (in_list ? x l).
+interpretation "list non-membership" 'notmem x l = (Not (in_list ? x l)).
+
+axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
+notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
+interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
+
+let rec FV M β‰ match M with 
+  [ par X β‡’ [X]
+  | app M1 M2 β‡’ FV M1@FV M2
+  | abs T M0 β‡’ FV M0
+  | _ β‡’ [ ] ].
+
+(* axiom Lookup : π”Έ β†’ Env β†’ option tp. *)
+
+(* forma alto livello del judgment
+   t_abs* : βˆ€G,T,X,M,U.
+            (βˆ€Y βˆ‰ supp(M).Judg (〈Y,TβŒͺ::G) (M[Y]) U) β†’ 
+            Judg G (Lam X T (M[X])) (arr T U) *)
+
+(* prima dimostrare, poi perfezionare gli assiomi, poi dimostrarli *)
+
+axiom Judg_ind : βˆ€P:Env β†’ tm β†’ tp β†’ Prop.
+  (βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ P G (par X) T) β†’ 
+  (βˆ€G,M,N,T,U.
+    Judg G M (arr T U) β†’ Judg G N T β†’ 
+    P G M (arr T U) β†’ P G N T β†’ P G (app M N) U) β†’ 
+  (βˆ€G,T1,T2,X,M1.
+    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ Judg (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’
+    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ P (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’ 
+    P G (Lam X T1 (sctx_app M1 X)) (arr T1 T2)) β†’ 
+  βˆ€G,M,T.Judg G M T β†’ P G M T.
+
+axiom t_par : βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ Judg G (par X) T.
+axiom t_app2 : βˆ€G,M,N,T,U.Judg G M (arr T U) β†’ Judg G N T β†’ Judg G (app M N) U.
+axiom t_Lam : βˆ€G,X,M,T,U.Judg (〈X,TβŒͺ::G) M U β†’ Judg G (Lam X T M) (arr T U).
+
+definition subenv β‰ Ξ»G1,G2.βˆ€x.x β—ƒ G1 β†’ x β—ƒ G2.
+interpretation "subenv" 'subseteq G1 G2 = (subenv G1 G2).
+
+axiom daemon : βˆ€P:Prop.P.
+
+theorem weakening : βˆ€G1,G2,M,T.G1 βŠ† G2 β†’ Judg G1 M T β†’ Judg G2 M T.
+#G1 #G2 #M #T #Hsub #HJ lapply Hsub lapply G2 -G2 change with (βˆ€G2.?)
+@(Judg_ind β€¦ HJ)
+[ #X #G #T0 #Hin #G2 #Hsub @t_par @Hsub //
+| #G #M0 #N #T0 #U #HM0 #HN #IH1 #IH2 #G2 #Hsub @t_app2
+  [| @IH1 // | @IH2 // ]
+| #G #T1 #T2 #X #M1 #HM1 #IH #G2 #Hsub @t_Lam @IH 
+  [ (* trivial property of Lam *) @daemon 
+  | (* trivial property of subenv *) @daemon ]
+]
+qed.
+
+(* Serve un tipo Tm per i termini localmente chiusi e i suoi principi di induzione e
+   ricorsione *)
\ No newline at end of file
diff --git a/matita/matita/broken_lib/binding/fp.ma b/matita/matita/broken_lib/binding/fp.ma
new file mode 100644 (file)
index 0000000..14ba2f7
--- /dev/null
@@ -0,0 +1,296 @@
+(**************************************************************************)
+(*       ___                                                              *)
+(*      ||M||                                                             *)
+(*      ||A||       A project by Andrea Asperti                           *)
+(*      ||T||                                                             *)
+(*      ||I||       Developers:                                           *)
+(*      ||T||         The HELM team.                                      *)
+(*      ||A||         http://helm.cs.unibo.it                             *)
+(*      \   /                                                             *)
+(*       \ /        This file is distributed under the terms of the       *)
+(*        v         GNU General Public License Version 2                  *)
+(*                                                                        *)
+(**************************************************************************)
+
+include "binding/names.ma".
+
+(* permutations *)
+definition finite_perm : βˆ€X:Nset.(X β†’ X) β†’ Prop β‰ 
+ Ξ»X,f.injective X X f βˆ§ surjective X X f βˆ§ βˆƒl.βˆ€x.x βˆ‰ l β†’ f x = x.
+
+(* maps a permutation to a list of parameters *)
+definition Pi_list : βˆ€X:Nset.(X β†’ X) β†’ list X β†’ list X β‰ 
+ Ξ»X,p,xl.map ?? (Ξ»x.p x) xl.
+
+interpretation "permutation of X list" 'middot p x = (Pi_list p x).
+
+definition swap : βˆ€N:Nset.N β†’ N β†’ N β†’ N β‰
+  Ξ»N,u,v,x.match (x == u) with
+    [true β‡’ v
+    |false β‡’ match (x == v) with
+       [true β‡’ u
+       |false β‡’ x]].
+       
+axiom swap_right : βˆ€N,x,y.swap N x y y = x.
+(*
+#N x y;nnormalize;nrewrite > (p_eqb3 ? y y β€¦);//;
+nlapply (refl ? (y β‰Ÿ x));ncases (y β‰Ÿ x) in βŠ’ (???% β†’ %);nnormalize;//;
+#H1;napply p_eqb1;//;
+nqed.
+*)
+
+axiom swap_left : βˆ€N,x,y.swap N x y x = y.
+(*
+#N x y;nnormalize;nrewrite > (p_eqb3 ? x x β€¦);//;
+nqed.
+*)
+
+axiom swap_other : βˆ€N,x,y,z.x β‰  z β†’ y β‰  z β†’ swap N x y z = z.
+(*
+#N x y z H1 H2;nnormalize;nrewrite > (p_eqb4 β€¦);
+##[nrewrite > (p_eqb4 β€¦);//;@;ncases H2;/2/;
+##|@;ncases H1;/2/
+##]
+nqed.
+*)
+
+axiom swap_inv : βˆ€N,x,y,z.swap N x y (swap N x y z) = z.
+(*
+#N x y z;nlapply (refl ? (x β‰Ÿ z));ncases (x β‰Ÿ z) in βŠ’ (???% β†’ ?);#H1
+##[nrewrite > (p_eqb1 β€¦ H1);nrewrite > (swap_left β€¦);//;
+##|nlapply (refl ? (y β‰Ÿ z));ncases (y β‰Ÿ z) in βŠ’ (???% β†’ ?);#H2
+   ##[nrewrite > (p_eqb1 β€¦ H2);nrewrite > (swap_right β€¦);//;
+   ##|nrewrite > (swap_other β€¦) in βŠ’ (??(????%)?);/2/;
+      nrewrite > (swap_other β€¦);/2/;
+   ##]
+##]
+nqed.
+*)
+
+axiom swap_fp : βˆ€N,x1,x2.finite_perm ? (swap N x1 x2).
+(*
+#N x1 x2;@
+##[@
+   ##[nwhd;#xa xb;nnormalize;nlapply (refl ? (xa β‰Ÿ x1));
+      ncases (xa β‰Ÿ x1) in βŠ’ (???% β†’ %);#H1
+      ##[nrewrite > (p_eqb1 β€¦ H1);nlapply (refl ? (xb β‰Ÿ x1));
+         ncases (xb β‰Ÿ x1) in βŠ’ (???% β†’ %);#H2
+         ##[nrewrite > (p_eqb1 β€¦ H2);//
+         ##|nlapply (refl ? (xb β‰Ÿ x2));
+            ncases (xb β‰Ÿ x2) in βŠ’ (???% β†’ %);#H3
+            ##[nnormalize;#H4;nrewrite > H4 in H3;
+               #H3;nrewrite > H3 in H2;#H2;ndestruct (H2)
+            ##|nnormalize;#H4;nrewrite > H4 in H3;
+               nrewrite > (p_eqb3 β€¦);//;#H5;ndestruct (H5)
+            ##]
+         ##]
+      ##|nlapply (refl ? (xa β‰Ÿ x2));
+         ncases (xa β‰Ÿ x2) in βŠ’ (???% β†’ %);#H2
+         ##[nrewrite > (p_eqb1 β€¦ H2);nlapply (refl ? (xb β‰Ÿ x1));
+            ncases (xb β‰Ÿ x1) in βŠ’ (???% β†’ %);#H3
+            ##[nnormalize;#H4;nrewrite > H4 in H3;
+               #H3;nrewrite > (p_eqb1 β€¦ H3);@
+            ##|nnormalize;nlapply (refl ? (xb β‰Ÿ x2));
+               ncases (xb β‰Ÿ x2) in βŠ’ (???% β†’ %);#H4
+               ##[nrewrite > (p_eqb1 β€¦ H4);//
+               ##|nnormalize;#H5;nrewrite > H5 in H3;
+                  nrewrite > (p_eqb3 β€¦);//;#H6;ndestruct (H6);
+               ##]
+            ##]
+         ##|nnormalize;nlapply (refl ? (xb β‰Ÿ x1));
+            ncases (xb β‰Ÿ x1) in βŠ’ (???% β†’ %);#H3
+            ##[nnormalize;#H4;nrewrite > H4 in H2;nrewrite > (p_eqb3 β€¦);//;
+               #H5;ndestruct (H5)
+            ##|nlapply (refl ? (xb β‰Ÿ x2));
+               ncases (xb β‰Ÿ x2) in βŠ’ (???% β†’ %);#H4
+               ##[nnormalize;#H5;nrewrite > H5 in H1;nrewrite > (p_eqb3 β€¦);//;
+                  #H6;ndestruct (H6)
+               ##|nnormalize;//
+               ##]
+            ##]
+         ##]
+      ##]
+   ##|nwhd;#z;nnormalize;nlapply (refl ? (z β‰Ÿ x1));
+      ncases (z β‰Ÿ x1) in βŠ’ (???% β†’ %);#H1
+      ##[nlapply (refl ? (z β‰Ÿ x2));
+         ncases (z β‰Ÿ x2) in βŠ’ (???% β†’ %);#H2
+         ##[@ z;nrewrite > H1;nrewrite > H2;napply p_eqb1;//
+         ##|@ x2;nrewrite > (p_eqb4 β€¦);
+            ##[nrewrite > (p_eqb3 β€¦);//;
+               nnormalize;napply p_eqb1;//
+            ##|nrewrite < (p_eqb1 β€¦ H1);@;#H3;nrewrite > H3 in H2;
+               nrewrite > (p_eqb3 β€¦);//;#H2;ndestruct (H2)
+            ##]
+         ##]
+      ##|nlapply (refl ? (z β‰Ÿ x2));
+         ncases (z β‰Ÿ x2) in βŠ’ (???% β†’ %);#H2
+         ##[@ x1;nrewrite > (p_eqb3 β€¦);//;
+            napply p_eqb1;nnormalize;//
+         ##|@ z;nrewrite > H1;nrewrite > H2;@;
+         ##]
+      ##]
+   ##]
+##|@ [x1;x2];#x0 H1;nrewrite > (swap_other β€¦)
+   ##[@
+   ##|@;#H2;nrewrite > H2 in H1;*;#H3;napply H3;/2/;
+   ##|@;#H2;nrewrite > H2 in H1;*;#H3;napply H3;//;
+   ##]
+##]
+nqed.
+*)
+
+axiom inj_swap : βˆ€N,u,v.injective ?? (swap N u v).
+(*
+#N u v;ncases (swap_fp N u v);*;#H1 H2 H3;//;
+nqed.
+*)
+
+axiom surj_swap : βˆ€N,u,v.surjective ?? (swap N u v).
+(*
+#N u v;ncases (swap_fp N u v);*;#H1 H2 H3;//;
+nqed.
+*)
+
+axiom finite_swap : βˆ€N,u,v.βˆƒl.βˆ€x.x βˆ‰ l β†’ swap N u v x = x.
+(*
+#N u v;ncases (swap_fp N u v);*;#H1 H2 H3;//;
+nqed.
+*)
+
+(* swaps two lists of parameters 
+definition Pi_swap_list : βˆ€xl,xl':list X.X β†’ X β‰ 
+ Ξ»xl,xl',x.foldr2 ??? (Ξ»u,v,r.swap ? u v r) x xl xl'.
+
+nlemma fp_swap_list : 
+  βˆ€xl,xl'.finite_perm ? (Pi_swap_list xl xl').
+#xl xl';@
+##[@;
+   ##[ngeneralize in match xl';nelim xl
+      ##[nnormalize;//;
+      ##|#x0 xl0;#IH xl'';nelim xl''
+         ##[nnormalize;//
+         ##|#x1 xl1 IH1 y0 y1;nchange in βŠ’ (??%% β†’ ?) with (swap ????);
+            #H1;nlapply (inj_swap β€¦ H1);#H2;
+            nlapply (IH β€¦ H2);//
+         ##]
+      ##]
+   ##|ngeneralize in match xl';nelim xl
+      ##[nnormalize;#_;#z;@z;@
+      ##|#x' xl0 IH xl'';nelim xl''
+         ##[nnormalize;#z;@z;@
+         ##|#x1 xl1 IH1 z;
+            nchange in βŠ’ (??(Ξ»_.???%)) with (swap ????);
+            ncases (surj_swap X x' x1 z);#x2 H1;
+            ncases (IH xl1 x2);#x3 H2;@ x3;
+            nrewrite < H2;napply H1
+         ##]
+      ##]
+   ##]
+##|ngeneralize in match xl';nelim xl
+   ##[#;@ [];#;@
+   ##|#x0 xl0 IH xl'';ncases xl''
+      ##[@ [];#;@
+      ##|#x1 xl1;ncases (IH xl1);#xl2 H1;
+         ncases (finite_swap X x0 x1);#xl3 H2;
+         @ (xl2@xl3);#x2 H3;
+         nchange in βŠ’ (??%?) with (swap ????);
+         nrewrite > (H1 β€¦);
+         ##[nrewrite > (H2 β€¦);//;@;#H4;ncases H3;#H5;napply H5;
+            napply in_list_to_in_list_append_r;//
+         ##|@;#H4;ncases H3;#H5;napply H5;
+            napply in_list_to_in_list_append_l;//
+         ##]
+      ##]
+   ##]
+##]
+nqed.
+
+(* the 'reverse' swap of lists of parameters 
+   composing Pi_swap_list and Pi_swap_list_r yields the identity function
+   (see the Pi_swap_list_inv lemma) *)
+ndefinition Pi_swap_list_r : βˆ€xl,xl':list X. Pi β‰ 
+ Ξ»xl,xl',x.foldl2 ??? (Ξ»r,u,v.swap ? u v r ) x xl xl'.
+
+nlemma fp_swap_list_r : 
+  βˆ€xl,xl'.finite_perm ? (Pi_swap_list_r xl xl').
+#xl xl';@
+##[@;
+   ##[ngeneralize in match xl';nelim xl
+      ##[nnormalize;//;
+      ##|#x0 xl0;#IH xl'';nelim xl''
+         ##[nnormalize;//
+         ##|#x1 xl1 IH1 y0 y1;nwhd in βŠ’ (??%% β†’ ?);
+            #H1;nlapply (IH β€¦ H1);#H2;
+            napply (inj_swap β€¦ H2);
+         ##]
+      ##]
+   ##|ngeneralize in match xl';nelim xl
+      ##[nnormalize;#_;#z;@z;@
+      ##|#x' xl0 IH xl'';nelim xl''
+         ##[nnormalize;#z;@z;@
+         ##|#x1 xl1 IH1 z;nwhd in βŠ’ (??(Ξ»_.???%));
+            ncases (IH xl1 z);#x2 H1;
+            ncases (surj_swap X x' x1 x2);#x3 H2;
+            @ x3;nrewrite < H2;napply H1;
+         ##]
+      ##]
+   ##]
+##|ngeneralize in match xl';nelim xl
+   ##[#;@ [];#;@
+   ##|#x0 xl0 IH xl'';ncases xl''
+      ##[@ [];#;@
+      ##|#x1 xl1;
+         ncases (IH xl1);#xl2 H1;
+         ncases (finite_swap X x0 x1);#xl3 H2;
+         @ (xl2@xl3);#x2 H3;nwhd in βŠ’ (??%?);
+         nrewrite > (H2 β€¦);
+         ##[nrewrite > (H1 β€¦);//;@;#H4;ncases H3;#H5;napply H5;
+            napply in_list_to_in_list_append_l;//
+         ##|@;#H4;ncases H3;#H5;napply H5;
+            napply in_list_to_in_list_append_r;//
+         ##]
+      ##]
+   ##]
+##]
+nqed.
+
+nlemma Pi_swap_list_inv :
+ βˆ€xl1,xl2,x.
+ Pi_swap_list xl1 xl2 (Pi_swap_list_r xl1 xl2 x) = x.
+#xl;nelim xl
+##[#;@
+##|#x1 xl1 IH xl';ncases xl'
+   ##[#;@
+   ##|#x2 xl2;#x;
+      nchange in βŠ’ (??%?) with 
+        (swap ??? (Pi_swap_list ?? 
+                  (Pi_swap_list_r ?? (swap ????))));
+      nrewrite > (IH xl2 ?);napply swap_inv;
+   ##]
+##]
+nqed.
+
+nlemma Pi_swap_list_fresh :
+  βˆ€x,xl1,xl2.x βˆ‰ xl1 β†’ x βˆ‰ xl2 β†’ Pi_swap_list xl1 xl2 x = x.
+#x xl1;nelim xl1
+##[#;@
+##|#x3 xl3 IH xl2' H1;ncases xl2'
+   ##[#;@
+   ##|#x4 xl4 H2;ncut (x βˆ‰ xl3 βˆ§ x βˆ‰ xl4);
+      ##[@
+         ##[@;#H3;ncases H1;#H4;napply H4;/2/;
+         ##|@;#H3;ncases H2;#H4;napply H4;/2/
+         ##]
+      ##] *; #H1' H2';
+      nchange in βŠ’ (??%?) with (swap ????);
+      nrewrite > (swap_other β€¦)
+      ##[napply IH;//;
+      ##|nchange in βŠ’ (?(???%)) with (Pi_swap_list ???);
+         nrewrite > (IH β€¦);//;@;#H3;ncases H2;#H4;napply H4;//;
+      ##|nchange in βŠ’ (?(???%)) with (Pi_swap_list ???);
+         nrewrite > (IH β€¦);//;@;#H3;ncases H1;#H4;napply H4;//
+      ##]
+   ##]
+##]
+nqed.
+*)
\ No newline at end of file
diff --git a/matita/matita/broken_lib/binding/ln.ma b/matita/matita/broken_lib/binding/ln.ma
new file mode 100644 (file)
index 0000000..ca7f574
--- /dev/null
@@ -0,0 +1,716 @@
+(**************************************************************************)
+(*       ___                                                              *)
+(*      ||M||                                                             *)
+(*      ||A||       A project by Andrea Asperti                           *)
+(*      ||T||                                                             *)
+(*      ||I||       Developers:                                           *)
+(*      ||T||         The HELM team.                                      *)
+(*      ||A||         http://helm.cs.unibo.it                             *)
+(*      \   /                                                             *)
+(*       \ /        This file is distributed under the terms of the       *)
+(*        v         GNU General Public License Version 2                  *)
+(*                                                                        *)
+(**************************************************************************)
+
+include "basics/lists/list.ma".
+include "basics/deqsets.ma".
+include "binding/names.ma".
+include "binding/fp.ma".
+
+axiom alpha : Nset.
+notation "𝔸" non associative with precedence 90 for @{'alphabet}.
+interpretation "set of names" 'alphabet = alpha.
+
+inductive tp : Type[0] β‰ 
+| top : tp
+| arr : tp β†’ tp β†’ tp.
+inductive pretm : Type[0] β‰ 
+| var : nat β†’ pretm
+| par :  π”Έ β†’ pretm
+| abs : tp β†’ pretm β†’ pretm
+| app : pretm β†’ pretm β†’ pretm.
+
+let rec Nth T n (l:list T) on n β‰ 
+  match l with 
+  [ nil β‡’ None ?
+  | cons hd tl β‡’ match n with
+    [ O β‡’ Some ? hd
+    | S n0 β‡’ Nth T n0 tl ] ].
+
+let rec vclose_tm_aux u x k β‰ match u with
+  [ var n β‡’ if (leb k n) then var (S n) else u
+  | par x0 β‡’ if (x0 == x) then (var k) else u
+  | app v1 v2 β‡’ app (vclose_tm_aux v1 x k) (vclose_tm_aux v2 x k)
+  | abs s v β‡’ abs s (vclose_tm_aux v x (S k)) ].
+definition vclose_tm β‰ Ξ»u,x.vclose_tm_aux u x O.  
+
+definition vopen_var β‰ Ξ»n,x,k.match eqb n k with
+ [ true β‡’ par x
+ | false β‡’ match leb n k with
+   [ true β‡’ var n
+   | false β‡’ var (pred n) ] ].
+
+let rec vopen_tm_aux u x k β‰ match u with
+  [ var n β‡’ vopen_var n x k
+  | par x0 β‡’ u
+  | app v1 v2 β‡’ app (vopen_tm_aux v1 x k) (vopen_tm_aux v2 x k)
+  | abs s v β‡’ abs s (vopen_tm_aux v x (S k)) ].
+definition vopen_tm β‰ Ξ»u,x.vopen_tm_aux u x O.
+
+let rec FV u β‰ match u with 
+  [ par x β‡’ [x]
+  | app v1 v2 β‡’ FV v1@FV v2
+  | abs s v β‡’ FV v
+  | _ β‡’ [ ] ].  
+
+definition lam β‰ Ξ»x,s,u.abs s (vclose_tm u x).
+
+let rec Pi_map_tm p u on u β‰ match u with
+[ par x β‡’ par (p x)
+| var _ β‡’ u
+| app v1 v2 β‡’ app (Pi_map_tm p v1) (Pi_map_tm p v2)
+| abs s v β‡’ abs s (Pi_map_tm p v) ].
+
+interpretation "permutation of tm" 'middot p x = (Pi_map_tm p x).
+
+notation "hvbox(u⌈xβŒ‰)"
+  with precedence 45
+  for @{ 'open $u $x }.
+
+(*
+notation "hvbox(u⌈xβŒ‰)"
+  with precedence 45
+  for @{ 'open $u $x }.
+notation "❴ u β΅ x" non associative with precedence 90 for @{ 'open $u $x }.
+*)
+interpretation "ln term variable open" 'open u x = (vopen_tm u x).
+notation < "hvbox(Ξ½ x break . u)"
+ with precedence 20
+for @{'nu $x $u }.
+notation > "Ξ½ list1 x sep , . term 19 u" with precedence 20
+  for ${ fold right @{$u} rec acc @{'nu $x $acc)} }.
+interpretation "ln term variable close" 'nu x u = (vclose_tm u x).
+
+let rec tm_height u β‰ match u with
+[ app v1 v2 β‡’ S (max (tm_height v1) (tm_height v2))
+| abs s v β‡’ S (tm_height v) 
+| _ β‡’ O ].
+
+theorem le_n_O_rect_Type0 : βˆ€n:nat. n β‰€ O β†’ βˆ€P: nat β†’Type[0]. P O β†’ P n.
+#n (cases n) // #a #abs cases (?:False) /2/ qed. 
+
+theorem nat_rect_Type0_1 : βˆ€n:nat.βˆ€P:nat β†’ Type[0]. 
+(βˆ€m.(βˆ€p. p < m β†’ P p) β†’ P m) β†’ P n.
+#n #P #H 
+cut (βˆ€q:nat. q β‰€ n β†’ P q) /2/
+(elim n) 
+ [#q #HleO (* applica male *) 
+    @(le_n_O_rect_Type0 ? HleO)
+    @H #p #ltpO cases (?:False) /2/ (* 3 *)
+ |#p #Hind #q #HleS 
+    @H #a #lta @Hind @le_S_S_to_le /2/
+ ]
+qed.
+
+lemma leb_false_to_lt : βˆ€n,m. leb n m = false β†’ m < n.
+#n elim n
+[ #m normalize #H destruct(H)
+| #n0 #IH * // #m normalize #H @le_S_S @IH // ]
+qed.
+
+lemma nominal_eta_aux : βˆ€x,u.x βˆ‰ FV u β†’ βˆ€k.vclose_tm_aux (vopen_tm_aux u x k) x k = u.
+#x #u elim u
+[ #n #_ #k normalize cases (decidable_eq_nat n k) #Hnk
+  [ >Hnk >eqb_n_n normalize >(\b ?) //
+  | >(not_eq_to_eqb_false β€¦ Hnk) normalize cases (true_or_false (leb n k)) #Hleb
+    [ >Hleb normalize >(?:leb k n = false) //
+      @lt_to_leb_false @not_eq_to_le_to_lt /2/
+    | >Hleb normalize >(?:leb k (pred n) = true) normalize
+      [ cases (leb_false_to_lt β€¦ Hleb) //
+      | @le_to_leb_true cases (leb_false_to_lt β€¦ Hleb) normalize /2/ ] ] ]
+| #y normalize #Hy >(\bf ?) // @(not_to_not β€¦ Hy) //
+| #s #v #IH normalize #Hv #k >IH // @Hv
+| #v1 #v2 #IH1 #IH2 normalize #Hv1v2 #k 
+  >IH1 [ >IH2 // | @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_l ]
+  @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_r ]
+qed.
+
+corollary nominal_eta : βˆ€x,u.x βˆ‰ FV u β†’ (Ξ½x.u⌈xβŒ‰) = u.
+#x #u #Hu @nominal_eta_aux //
+qed.
+
+lemma eq_height_vopen_aux : βˆ€v,x,k.tm_height (vopen_tm_aux v x k) = tm_height v.
+#v #x elim v
+[ #n #k normalize cases (eqb n k) // cases (leb n k) //
+| #u #k %
+| #s #u #IH #k normalize >IH %
+| #u1 #u2 #IH1 #IH2 #k normalize >IH1 >IH2 % ]
+qed.
+
+corollary eq_height_vopen : βˆ€v,x.tm_height (v⌈xβŒ‰) = tm_height v.
+#v #x @eq_height_vopen_aux
+qed.
+
+theorem pretm_ind_plus_aux : 
+ βˆ€P:pretm β†’ Type[0].
+   (βˆ€x:𝔸.P (par x)) β†’ 
+   (βˆ€n:β„•.P (var n)) β†’ 
+   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
+ βˆ€n,u.tm_height u β‰€ n β†’ P u.
+#P #Hpar #Hvar #Happ #C #Hlam #n change with ((Ξ»n.?) n); @(nat_rect_Type0_1 n ??)
+#m cases m
+[ #_ * /2/
+  [ normalize #s #v #Hfalse cases (?:False) cases (not_le_Sn_O (tm_height v)) /2/
+  | #v1 #v2 whd in βŠ’ (?%?β†’?); #Hfalse cases (?:False) cases (not_le_Sn_O (max ??))
+    [ #H @H @Hfalse|*:skip] ] ]
+-m #m #IH * /2/
+[ #s #v whd in βŠ’ (?%?β†’?); #Hv
+  lapply (p_fresh β€¦ (C@FV v)) letin y β‰ (N_fresh β€¦ (C@FV v)) #Hy
+  >(?:abs s v = lam y s (v⌈yβŒ‰))
+  [| whd in βŠ’ (???%); >nominal_eta // @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r ] 
+  @Hlam
+  [ @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r
+  | @(not_to_not β€¦ Hy) @in_list_to_in_list_append_l ]
+  @IH [| @Hv | >eq_height_vopen % ]
+| #v1 #v2 whd in βŠ’ (?%?β†’?); #Hv @Happ
+  [ @IH [| @Hv | @le_max_1 ] | @IH [| @Hv | @le_max_2 ] ] ]
+qed.
+
+corollary pretm_ind_plus :
+ βˆ€P:pretm β†’ Type[0].
+   (βˆ€x:𝔸.P (par x)) β†’ 
+   (βˆ€n:β„•.P (var n)) β†’ 
+   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
+ βˆ€u.P u.
+#P #Hpar #Hvar #Happ #C #Hlam #u @pretm_ind_plus_aux /2/
+qed.
+
+(* maps a permutation to a list of terms *)
+definition Pi_map_list : (𝔸 β†’ π”Έ) β†’ list π”Έ β†’ list π”Έ β‰ map π”Έ π”Έ .
+
+(* interpretation "permutation of name list" 'middot p x = (Pi_map_list p x).*)
+
+(*
+inductive tm : pretm β†’ Prop β‰ 
+| tm_par : βˆ€x:𝔸.tm (par x)
+| tm_app : βˆ€u,v.tm u β†’ tm v β†’ tm (app u v)
+| tm_lam : βˆ€x,s,u.tm u β†’ tm (lam x s u).
+
+inductive ctx_aux : nat β†’ pretm β†’ Prop β‰ 
+| ctx_var : βˆ€n,k.n < k β†’ ctx_aux k (var n)
+| ctx_par : βˆ€x,k.ctx_aux k (par x)
+| ctx_app : βˆ€u,v,k.ctx_aux k u β†’ ctx_aux k v β†’ ctx_aux k (app u v)
+(* Γ¨ sostituibile da ctx_lam ? *)
+| ctx_abs : βˆ€s,u.ctx_aux (S k) u β†’ ctx_aux k (abs s u).
+*)
+
+inductive tm_or_ctx (k:nat) : pretm β†’ Type[0] β‰ 
+| toc_var : βˆ€n.n < k β†’ tm_or_ctx k (var n)
+| toc_par : βˆ€x.tm_or_ctx k (par x)
+| toc_app : βˆ€u,v.tm_or_ctx k u β†’ tm_or_ctx k v β†’ tm_or_ctx k (app u v)
+| toc_lam : βˆ€x,s,u.tm_or_ctx k u β†’ tm_or_ctx k (lam x s u).
+
+definition tm β‰ Ξ»t.tm_or_ctx O t.
+definition ctx β‰ Ξ»t.tm_or_ctx 1 t.
+
+definition check_tm β‰ Ξ»u,k.
+  pretm_ind_plus ?
+  (Ξ»_.true)
+  (Ξ»n.leb (S n) k)
+  (Ξ»v1,v2,rv1,rv2.rv1 βˆ§ rv2)
+  [] (Ξ»x,s,v,px,pC,rv.rv)
+  u.
+
+axiom pretm_ind_plus_app : βˆ€P,u,v,C,H1,H2,H3,H4.
+  pretm_ind_plus P H1 H2 H3 C H4 (app u v) = 
+    H3 u v (pretm_ind_plus P H1 H2 H3 C H4 u) (pretm_ind_plus P H1 H2 H3 C H4 v).
+
+axiom pretm_ind_plus_lam : βˆ€P,x,s,u,C,px,pC,H1,H2,H3,H4.
+  pretm_ind_plus P H1 H2 H3 C H4 (lam x s (u⌈xβŒ‰)) = 
+    H4 x s u px pC (pretm_ind_plus P H1 H2 H3 C H4 (u⌈xβŒ‰)).
+
+record TM : Type[0] β‰ {
+  pretm_of_TM :> pretm;
+  tm_of_TM : check_tm pretm_of_TM O = true
+}.
+
+record CTX : Type[0] β‰ {
+  pretm_of_CTX :> pretm;
+  ctx_of_CTX : check_tm pretm_of_CTX 1 = true
+}.
+
+inductive tm2 : pretm β†’ Type[0] β‰ 
+| tm_par : βˆ€x.tm2 (par x)
+| tm_app : βˆ€u,v.tm2 u β†’ tm2 v β†’ tm2 (app u v)
+| tm_lam : βˆ€x,s,u.x βˆ‰ FV u β†’ (βˆ€y.y βˆ‰ FV u β†’ tm2 (u⌈yβŒ‰)) β†’ tm2 (lam x s (u⌈xβŒ‰)).
+
+(*
+inductive tm' : pretm β†’ Prop β‰ 
+| tm_par : βˆ€x.tm' (par x)
+| tm_app : βˆ€u,v.tm' u β†’ tm' v β†’ tm' (app u v)
+| tm_lam : βˆ€x,s,u,C.x βˆ‰ FV u β†’ x βˆ‰ C β†’ (βˆ€y.y βˆ‰ FV u β†’ tm' (❴u❡y)) β†’ tm' (lam x s (❴u❡x)).
+*)
+
+lemma pi_vclose_tm : 
+  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(Ξ½x.u) = (Ξ½ swap ? z1 z2 x.swap π”Έ z1 z2 Β· u).
+#z1 #z2 #x #u
+change with (vclose_tm_aux ???) in match (vclose_tm ??);
+change with (vclose_tm_aux ???) in βŠ’ (???%); lapply O elim u normalize //
+[ #n #k cases (leb k n) normalize %
+| #x0 #k cases (true_or_false (x0==z1)) #H1 >H1 normalize
+  [ cases (true_or_false (x0==x)) #H2 >H2 normalize
+    [ <(\P H2) >H1 normalize >(\b (refl ? z2)) %
+    | >H1 normalize cases (true_or_false (x==z1)) #H3 >H3 normalize
+      [ >(\P H3) in H2; >H1 #Hfalse destruct (Hfalse)
+      | cases (true_or_false (x==z2)) #H4 >H4 normalize
+        [ cases (true_or_false (z2==z1)) #H5 >H5 normalize //
+          >(\P H5) in H4; >H3 #Hfalse destruct (Hfalse)
+        | >(\bf ?) // @sym_not_eq @(\Pf H4) ]
+      ]
+    ]
+  | cases (true_or_false (x0==x)) #H2 >H2 normalize
+    [ <(\P H2) >H1 normalize >(\b (refl ??)) %
+    | >H1 normalize cases (true_or_false (x==z1)) #H3 >H3 normalize
+      [ cases (true_or_false (x0==z2)) #H4 >H4 normalize 
+        [ cases (true_or_false (z1==z2)) #H5 >H5 normalize //
+          <(\P H5) in H4; <(\P H3) >H2 #Hfalse destruct (Hfalse)
+        | >H4 % ]
+      | cases (true_or_false (x0==z2)) #H4 >H4 normalize
+        [ cases (true_or_false (x==z2)) #H5 >H5 normalize 
+          [ <(\P H5) in H4; >H2 #Hfalse destruct (Hfalse)
+          | >(\bf ?) // @sym_not_eq @(\Pf H3) ]
+        | cases (true_or_false (x==z2)) #H5 >H5 normalize
+          [ >H1 %
+          | >H2 % ]
+        ]
+      ]
+    ]
+  ]
+]
+qed.
+
+lemma pi_vopen_tm : 
+  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(u⌈xβŒ‰) = (swap π”Έ z1 z2 Β· u⌈swap π”Έ z1 z2 xβŒ‰).
+#z1 #z2 #x #u
+change with (vopen_tm_aux ???) in match (vopen_tm ??);
+change with (vopen_tm_aux ???) in βŠ’ (???%); lapply O elim u normalize //
+#n #k cases (true_or_false (eqb n k)) #H1 >H1 normalize //
+cases (true_or_false (leb n k)) #H2 >H2 normalize //
+qed.
+
+lemma pi_lam : 
+  βˆ€z1,z2,x,s,u.swap π”Έ z1 z2 Β· lam x s u = lam (swap π”Έ z1 z2 x) s (swap π”Έ z1 z2 Β· u).
+#z1 #z2 #x #s #u whd in βŠ’ (???%); <(pi_vclose_tm β€¦) %
+qed.
+
+lemma eqv_FV : βˆ€z1,z2,u.FV (swap π”Έ z1 z2 Β· u) = Pi_map_list (swap π”Έ z1 z2) (FV u).
+#z1 #z2 #u elim u //
+[ #s #v normalize //
+| #v1 #v2 normalize /2/ ]
+qed.
+
+lemma swap_inv_tm : βˆ€z1,z2,u.swap π”Έ z1 z2 Β· (swap π”Έ z1 z2 Β· u) = u.
+#z1 #z2 #u elim u [1,3,4:normalize //]
+#x whd in βŠ’ (??%?); >swap_inv %
+qed.
+
+lemma eqv_in_list : βˆ€x,l,z1,z2.x βˆˆ l β†’ swap π”Έ z1 z2 x βˆˆ Pi_map_list (swap π”Έ z1 z2) l.
+#x #l #z1 #z2 #Hin elim Hin
+[ #x0 #l0 %
+| #x1 #x2 #l0 #Hin #IH %2 @IH ]
+qed.
+
+lemma eqv_tm2 : βˆ€u.tm2 u β†’ βˆ€z1,z2.tm2 ((swap ? z1 z2)Β·u).
+#u #Hu #z1 #z2 letin p β‰ (swap ? z1 z2) elim Hu /2/
+#x #s #v #Hx #Hv #IH >pi_lam >pi_vopen_tm %3
+[ @(not_to_not β€¦ Hx) -Hx #Hx
+  <(swap_inv ? z1 z2 x) <(swap_inv_tm z1 z2 v) >eqv_FV @eqv_in_list //
+| #y #Hy <(swap_inv ? z1 z2 y)
+  <pi_vopen_tm @IH @(not_to_not β€¦ Hy) -Hy #Hy <(swap_inv ? z1 z2 y)
+  >eqv_FV @eqv_in_list //
+]
+qed.
+
+lemma vclose_vopen_aux : βˆ€x,u,k.vopen_tm_aux (vclose_tm_aux u x k) x k = u.
+#x #u elim u normalize //
+[ #n #k cases (true_or_false (leb k n)) #H >H whd in βŠ’ (??%?);
+  [ cases (true_or_false (eqb (S n) k)) #H1 >H1
+    [ <(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_true_to_le β€¦ H) -H #H
+      cases (le_to_not_lt β€¦ H) -H #H cases (H ?) %
+    | whd in βŠ’ (??%?); >lt_to_leb_false // @le_S_S /2/ ]
+  | cases (true_or_false (eqb n k)) #H1 >H1 normalize
+    [ >(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_false_to_not_le β€¦ H) -H
+      * #H cases (H ?) %
+    | >le_to_leb_true // @not_lt_to_le % #H2 >le_to_leb_true in H;
+      [ #H destruct (H) | /2/ ]
+    ]
+  ]
+| #x0 #k cases (true_or_false (x0==x)) #H1 >H1 normalize // >(\P H1) >eqb_n_n % ]
+qed.      
+
+lemma vclose_vopen : βˆ€x,u.((Ξ½x.u)⌈xβŒ‰) = u. #x #u @vclose_vopen_aux
+qed.
+
+(*
+theorem tm_to_tm : βˆ€t.tm' t β†’ tm t.
+#t #H elim H
+*)
+
+lemma in_list_singleton : βˆ€T.βˆ€t1,t2:T.t1 βˆˆ [t2] β†’ t1 = t2.
+#T #t1 #t2 #H @(in_list_inv_ind ??? H) /2/
+qed.
+
+lemma fresh_vclose_tm_aux : βˆ€u,x,k.x βˆ‰ FV (vclose_tm_aux u x k).
+#u #x elim u //
+[ #n #k normalize cases (leb k n) normalize //
+| #x0 #k normalize cases (true_or_false (x0==x)) #H >H normalize //
+  lapply (\Pf H) @not_to_not #Hin >(in_list_singleton ??? Hin) %
+| #v1 #v2 #IH1 #IH2 #k normalize % #Hin cases (in_list_append_to_or_in_list ???? Hin) /2/ ]
+qed.
+
+lemma fresh_vclose_tm : βˆ€u,x.x βˆ‰ FV (Ξ½x.u). //
+qed.
+
+lemma check_tm_true_to_toc : βˆ€u,k.check_tm u k = true β†’ tm_or_ctx k u.
+#u @(pretm_ind_plus ???? [ ] ? u)
+[ #x #k #_ %2
+| #n #k change with (leb (S n) k) in βŠ’ (??%?β†’?); #H % @leb_true_to_le //
+| #v1 #v2 #rv1 #rv2 #k change with (pretm_ind_plus ???????) in βŠ’ (??%?β†’?);
+  >pretm_ind_plus_app #H cases (andb_true ?? H) -H #Hv1 #Hv2 %3
+  [ @rv1 @Hv1 | @rv2 @Hv2 ]
+| #x #s #v #Hx #_ #rv #k change with (pretm_ind_plus ???????) in βŠ’ (??%?β†’?); 
+  >pretm_ind_plus_lam // #Hv %4 @rv @Hv ]
+qed.
+
+lemma toc_to_check_tm_true : βˆ€u,k.tm_or_ctx k u β†’ check_tm u k = true.
+#u #k #Hu elim Hu //
+[ #n #Hn change with (leb (S n) k) in βŠ’ (??%?); @le_to_leb_true @Hn
+| #v1 #v2 #Hv1 #Hv2 #IH1 #IH2 change with (pretm_ind_plus ???????) in βŠ’ (??%?);
+  >pretm_ind_plus_app change with (check_tm v1 k βˆ§ check_tm v2 k) in βŠ’ (??%?); /2/
+| #x #s #v #Hv #IH <(vclose_vopen x v) change with (pretm_ind_plus ???????) in βŠ’ (??%?);
+  >pretm_ind_plus_lam [| // | @fresh_vclose_tm ] >(vclose_vopen x v) @IH ]
+qed.
+
+lemma fresh_swap_tm : βˆ€z1,z2,u.z1 βˆ‰ FV u β†’ z2 βˆ‰ FV u β†’ swap π”Έ z1 z2 Β· u = u.
+#z1 #z2 #u elim u
+[2: normalize in βŠ’ (?β†’%β†’%β†’?); #x #Hz1 #Hz2 whd in βŠ’ (??%?); >swap_other //
+  [ @(not_to_not β€¦ Hz2) | @(not_to_not β€¦ Hz1) ] //
+|1: //
+| #s #v #IH normalize #Hz1 #Hz2 >IH // [@Hz2|@Hz1]
+| #v1 #v2 #IH1 #IH2 normalize #Hz1 #Hz2
+  >IH1 [| @(not_to_not β€¦ Hz2) @in_list_to_in_list_append_l | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_l ]
+  >IH2 // [@(not_to_not β€¦ Hz2) @in_list_to_in_list_append_r | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_r ]
+]
+qed.
+
+theorem tm_to_tm2 : βˆ€u.tm u β†’ tm2 u.
+#t #Ht elim Ht
+[ #n #Hn cases (not_le_Sn_O n) #Hfalse cases (Hfalse Hn)
+| @tm_par
+| #u #v #Hu #Hv @tm_app
+| #x #s #u #Hu #IHu <(vclose_vopen x u) @tm_lam
+  [ @fresh_vclose_tm
+  | #y #Hy <(fresh_swap_tm x y (Ξ½x.u)) /2/ @fresh_vclose_tm ]
+]
+qed.
+
+theorem tm2_to_tm : βˆ€u.tm2 u β†’ tm u.
+#u #pu elim pu /2/ #x #s #v #Hx #Hv #IH %4 @IH //
+qed.
+
+(* define PAR APP LAM *)
+definition PAR β‰ Ξ»x.mk_TM (par x) ?. // qed.
+definition APP β‰ Ξ»u,v:TM.mk_TM (app u v) ?.
+change with (pretm_ind_plus ???????) in match (check_tm ??); >pretm_ind_plus_app
+change with (check_tm ??) in match (pretm_ind_plus ???????); change with (check_tm ??) in match (pretm_ind_plus ???????) in βŠ’ (??(??%)?);
+@andb_elim >(tm_of_TM u) >(tm_of_TM v) % qed.
+definition LAM β‰ Ξ»x,s.Ξ»u:TM.mk_TM (lam x s u) ?.
+change with (pretm_ind_plus ???????) in match (check_tm ??); <(vclose_vopen x u)
+>pretm_ind_plus_lam [| // | @fresh_vclose_tm ]
+change with (check_tm ??) in match (pretm_ind_plus ???????); >vclose_vopen
+@(tm_of_TM u) qed.
+
+axiom vopen_tm_down : βˆ€u,x,k.tm_or_ctx (S k) u β†’ tm_or_ctx k (u⌈xβŒ‰).
+(* needs true_plus_false
+
+#u #x #k #Hu elim Hu
+[ #n #Hn normalize cases (true_or_false (eqb n O)) #H >H [%2]
+  normalize >(?: leb n O = false) [|cases n in H; // >eqb_n_n #H destruct (H) ]
+  normalize lapply Hn cases n in H; normalize [ #Hfalse destruct (Hfalse) ]
+  #n0 #_ #Hn0 % @le_S_S_to_le //
+| #x0 %2
+| #v1 #v2 #Hv1 #Hv2 #IH1 #IH2 %3 //
+| #x0 #s #v #Hv #IH normalize @daemon
+]
+qed.
+*)
+
+definition vopen_TM β‰ Ξ»u:CTX.Ξ»x.mk_TM (u⌈xβŒ‰) ?.
+@toc_to_check_tm_true @vopen_tm_down @check_tm_true_to_toc @ctx_of_CTX qed.
+
+axiom vclose_tm_up : βˆ€u,x,k.tm_or_ctx k u β†’ tm_or_ctx (S k) (Ξ½x.u).
+
+definition vclose_TM β‰ Ξ»u:TM.Ξ»x.mk_CTX (Ξ½x.u) ?. 
+@toc_to_check_tm_true @vclose_tm_up @check_tm_true_to_toc @tm_of_TM qed.
+
+interpretation "ln wf term variable open" 'open u x = (vopen_TM u x).
+interpretation "ln wf term variable close" 'nu x u = (vclose_TM u x).
+
+theorem tm_alpha : βˆ€x,y,s,u.x βˆ‰ FV u β†’ y βˆ‰ FV u β†’ lam x s (u⌈xβŒ‰) = lam y s (u⌈yβŒ‰).
+#x #y #s #u #Hx #Hy whd in βŠ’ (??%%); @eq_f >nominal_eta // >nominal_eta //
+qed.
+
+lemma TM_to_tm2 : βˆ€u:TM.tm2 u.
+#u @tm_to_tm2 @check_tm_true_to_toc @tm_of_TM qed.
+
+theorem TM_ind_plus_weak : 
+ βˆ€P:pretm β†’ Type[0].
+   (βˆ€x:𝔸.P (PAR x)) β†’ 
+   (βˆ€v1,v2:TM.P v1 β†’ P v2 β†’ P (APP v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s.βˆ€v:CTX.x βˆ‰ FV v β†’ x βˆ‰ C β†’ 
+     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (LAM x s (v⌈xβŒ‰))) β†’
+ βˆ€u:TM.P u.
+#P #Hpar #Happ #C #Hlam #u elim (TM_to_tm2 u) //
+[ #v1 #v2 #pv1 #pv2 #IH1 #IH2 @(Happ (mk_TM β€¦) (mk_TM β€¦) IH1 IH2)
+  @toc_to_check_tm_true @tm2_to_tm //
+| #x #s #v #Hx #pv #IH
+  lapply (p_fresh β€¦ (C@FV v)) letin x0 β‰ (N_fresh β€¦ (C@FV v)) #Hx0
+  >(?:lam x s (v⌈xβŒ‰) = lam x0 s (v⌈x0βŒ‰))
+  [|@tm_alpha // @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r ]
+  @(Hlam x0 s (mk_CTX v ?) ??)
+  [ <(nominal_eta β€¦ Hx) @toc_to_check_tm_true @vclose_tm_up @tm2_to_tm @pv //
+  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r
+  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_l
+  | @IH ]
+]
+qed.
+
+lemma eq_mk_TM : βˆ€u,v.u = v β†’ βˆ€pu,pv.mk_TM u pu = mk_TM v pv.
+#u #v #Heq >Heq #pu #pv %
+qed.
+
+lemma eq_P : βˆ€T:Type[0].βˆ€t1,t2:T.t1 = t2 β†’ βˆ€P:T β†’ Type[0].P t1 β†’ P t2. // qed.
+
+theorem TM_ind_plus :
+ βˆ€P:TM β†’ Type[0].
+   (βˆ€x:𝔸.P (PAR x)) β†’ 
+   (βˆ€v1,v2:TM.P v1 β†’ P v2 β†’ P (APP v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s.βˆ€v:CTX.x βˆ‰ FV v β†’ x βˆ‰ C β†’ 
+     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (LAM x s (v⌈xβŒ‰))) β†’
+ βˆ€u:TM.P u.
+#P #Hpar #Happ #C #Hlam * #u #pu
+>(?:mk_TM u pu = 
+    mk_TM u (toc_to_check_tm_true β€¦ (tm2_to_tm β€¦ (tm_to_tm2 β€¦ (check_tm_true_to_toc β€¦ pu))))) [|%]
+elim (tm_to_tm2 u ?) //
+[ #v1 #v2 #pv1 #pv2 #IH1 #IH2 @(Happ (mk_TM β€¦) (mk_TM β€¦) IH1 IH2)
+| #x #s #v #Hx #pv #IH
+  lapply (p_fresh β€¦ (C@FV v)) letin x0 β‰ (N_fresh β€¦ (C@FV v)) #Hx0
+  lapply (Hlam x0 s (mk_CTX v ?) ???) 
+  [2: @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_l @Hx0
+  |4: @toc_to_check_tm_true <(nominal_eta x v) // @vclose_tm_up @tm2_to_tm @pv // 
+  | #y #Hy whd in match (vopen_TM ??);
+    >(?:mk_TM (v⌈yβŒ‰) ? = mk_TM (v⌈yβŒ‰) (toc_to_check_tm_true (v⌈yβŒ‰) O (tm2_to_tm (v⌈yβŒ‰) (pv y Hy))))
+    [@IH|%]
+  | @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_r @Hx0 
+  | @eq_P @eq_mk_TM whd in match (vopen_TM ??); @tm_alpha // @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r ]
+]
+qed.
+
+notation 
+"hvbox('nominal' u 'return' out 'with' 
+       [ 'xpar' ident x β‡’ f1 
+       | 'xapp' ident v1 ident v2 ident recv1 ident recv2 β‡’ f2 
+       | 'xlam' β¨ident y # C❩ ident s ident w ident py1 ident py2 ident recw β‡’ f3 ])"
+with precedence 48 
+for @{ TM_ind_plus $out (Ξ»${ident x}:?.$f1)
+       (Ξ»${ident v1}:?.Ξ»${ident v2}:?.Ξ»${ident recv1}:?.Ξ»${ident recv2}:?.$f2)
+       $C (Ξ»${ident y}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.Ξ»${ident recw}:?.$f3)
+       $u }.
+       
+(* include "basics/jmeq.ma".*)
+
+definition subst β‰ (Ξ»u:TM.Ξ»x,v.
+  nominal u return (Ξ»_.TM) with 
+  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ PAR x0 ]  (* u instead of PAR x0 does not work, u stays the same at every rec call! *)
+  | xapp v1 v2 recv1 recv2 β‡’ APP recv1 recv2
+  | xlam β¨y # x::FV v❩ s w py1 py2 recw β‡’ LAM y s (recw y py1) ]).
+  
+lemma subst_def : βˆ€u,x,v.subst u x v =
+  nominal u return (Ξ»_.TM) with 
+  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ PAR x0 ]
+  | xapp v1 v2 recv1 recv2 β‡’ APP recv1 recv2
+  | xlam β¨y # x::FV v❩ s w py1 py2 recw β‡’ LAM y s (recw y py1) ]. //
+qed.
+
+axiom TM_ind_plus_LAM : 
+  βˆ€x,s,u,out,f1,f2,C,f3,Hx1,Hx2.
+  TM_ind_plus out f1 f2 C f3 (LAM x s (u⌈xβŒ‰)) = 
+  f3 x s u Hx1 Hx2 (Ξ»y,Hy.TM_ind_plus ? f1 f2 C f3 ?).
+  
+axiom TM_ind_plus_APP : 
+  βˆ€u1,u2,out,f1,f2,C,f3.
+  TM_ind_plus out f1 f2 C f3 (APP u1 u2) = 
+  f2 u1 u2 (TM_ind_plus out f1 f2 C f3 ?) (TM_ind_plus out f1 f2 C f3 ?).
+  
+lemma eq_mk_CTX : βˆ€u,v.u = v β†’ βˆ€pu,pv.mk_CTX u pu = mk_CTX v pv.
+#u #v #Heq >Heq #pu #pv %
+qed.
+
+lemma vclose_vopen_TM : βˆ€x.βˆ€u:TM.((Ξ½x.u)⌈xβŒ‰) = u.
+#x * #u #pu @eq_mk_TM @vclose_vopen qed.
+
+lemma nominal_eta_CTX : βˆ€x.βˆ€u:CTX.x βˆ‰ FV u β†’ (Ξ½x.(u⌈xβŒ‰)) = u.
+#x * #u #pu #Hx @eq_mk_CTX @nominal_eta // qed. 
+
+theorem TM_alpha : βˆ€x,y,s.βˆ€u:CTX.x βˆ‰ FV u β†’ y βˆ‰ FV u β†’ LAM x s (u⌈xβŒ‰) = LAM y s (u⌈yβŒ‰).
+#x #y #s #u #Hx #Hy @eq_mk_TM @tm_alpha // qed.
+
+axiom in_vopen_CTX : βˆ€x,y.βˆ€v:CTX.x βˆˆ FV (v⌈yβŒ‰) β†’ x = y βˆ¨ x βˆˆ FV v.
+
+theorem subst_fresh : βˆ€u,v:TM.βˆ€x.x βˆ‰ FV u β†’ subst u x v = u.
+#u #v #x @(TM_ind_plus β€¦ (x::FV v) β€¦ u)
+[ #x0 normalize in βŠ’ (%β†’?); #Hx normalize in βŠ’ (??%?);
+  >(\bf ?) [| @(not_to_not β€¦ Hx) #Heq >Heq % ] %
+| #u1 #u2 #IH1 #IH2 normalize in βŠ’ (%β†’?); #Hx
+  >subst_def >TM_ind_plus_APP @eq_mk_TM @eq_f2 @eq_f
+  [ <subst_def @IH1 @(not_to_not β€¦ Hx) @in_list_to_in_list_append_l
+  | <subst_def @IH2 @(not_to_not β€¦ Hx) @in_list_to_in_list_append_r ]
+| #x0 #s #v0 #Hx0 #HC #IH #Hx >subst_def >TM_ind_plus_LAM [|@HC|@Hx0]
+  @eq_f <subst_def @IH // @(not_to_not β€¦ Hx) -Hx #Hx
+  change with (FV (Ξ½x0.(v0⌈x0βŒ‰))) in βŠ’ (???%); >nominal_eta_CTX //
+  cases (in_vopen_CTX β€¦ Hx) // #Heq >Heq in HC; * #HC @False_ind @HC %
+]
+qed.
+
+example subst_LAM_same : βˆ€x,s,u,v. subst (LAM x s u) x v = LAM x s u.
+#x #s #u #v >subst_def <(vclose_vopen_TM x u)
+lapply (p_fresh β€¦ (FV (Ξ½x.u)@x::FV v)) letin x0 β‰ (N_fresh β€¦ (FV (Ξ½x.u)@x::FV v)) #Hx0
+>(TM_alpha x x0)
+[| @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_l @Hx0 | @fresh_vclose_tm ]
+>TM_ind_plus_LAM [| @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_r @Hx0 | @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_l @Hx0 ]
+@eq_f change with (subst ((Ξ½x.u)⌈x0βŒ‰) x v) in βŠ’ (??%?); @subst_fresh
+@(not_to_not β€¦ Hx0) #Hx0' cases (in_vopen_CTX β€¦ Hx0') 
+[ #Heq >Heq @in_list_to_in_list_append_r %
+| #Hfalse @False_ind cases (fresh_vclose_tm u x) #H @H @Hfalse ]
+qed.
+
+(*
+notation > "Ξ› ident x. ident T [ident x] β†¦ P"
+  with precedence 48 for @{'foo (Ξ»${ident x}.Ξ»${ident T}.$P)}.
+
+notation < "Ξ› ident x. ident T [ident x] β†¦ P"
+  with precedence 48 for @{'foo (Ξ»${ident x}:$Q.Ξ»${ident T}:$R.$P)}.
+*)
+
+(*
+notation 
+"hvbox('nominal' u 'with' 
+       [ 'xpar' ident x β‡’ f1 
+       | 'xapp' ident v1 ident v2  β‡’ f2
+       | 'xlam' ident x # C s w β‡’ f3 ])"
+with precedence 48 
+for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
+ (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
+ $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
+*)
+
+(*
+notation 
+"hvbox('nominal' u 'with' 
+       [ 'xpar' ident x ^ f1 
+       | 'xapp' ident v1 ident v2 ^ f2 ])"
+(*       | 'xlam' ident x # C s w ^ f3 ]) *)
+with precedence 48 
+for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
+ (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
+ $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
+*)
+notation 
+"hvbox('nominal' u 'with' 
+       [ 'xpar' ident x ^ f1 
+       | 'xapp' ident v1 ident v2 ^ f2 ])"
+with precedence 48 
+for @{ tm2_ind_plus ? (Ξ»${ident x}:?.$f1) 
+ (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
+ $C (Ξ»${ident x}:?.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
+
+axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
+notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
+interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
+
+
+
+inductive judg : list tp β†’ tm β†’ tp β†’ Prop β‰ 
+| t_var : βˆ€g,n,t.Nth ? n g = Some ? t β†’ judg g (var n) t
+| t_app : βˆ€g,m,n,t,u.judg g m (arr t u) β†’ judg g n t β†’ judg g (app m n) u
+| t_abs : βˆ€g,t,m,u.judg (t::g) m u β†’ judg g (abs t m) (arr t u).
+
+definition Env := list (𝔸 Γ— tp).
+
+axiom vclose_env : Env β†’ list tp.
+axiom vclose_tm : Env β†’ tm β†’ tm.
+axiom Lam : π”Έ β†’ tp β†’ tm β†’ tm.
+definition Judg β‰ Ξ»G,M,T.judg (vclose_env G) (vclose_tm G M) T.
+definition dom β‰ Ξ»G:Env.map ?? (fst ??) G.
+
+definition sctx β‰ π”Έ Γ— tm.
+axiom swap_tm : π”Έ β†’ π”Έ β†’ tm β†’ tm.
+definition sctx_app : sctx β†’ π”Έ β†’ tm β‰ Ξ»M0,Y.let βŒ©X,MβŒͺ β‰ M0 in swap_tm X Y M.
+
+axiom in_list : βˆ€A:Type[0].A β†’ list A β†’ Prop.
+interpretation "list membership" 'mem x l = (in_list ? x l).
+interpretation "list non-membership" 'notmem x l = (Not (in_list ? x l)).
+
+axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
+notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
+interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
+
+(* axiom Lookup : π”Έ β†’ Env β†’ option tp. *)
+
+(* forma alto livello del judgment
+   t_abs* : βˆ€G,T,X,M,U.
+            (βˆ€Y βˆ‰ supp(M).Judg (〈Y,TβŒͺ::G) (M[Y]) U) β†’ 
+            Judg G (Lam X T (M[X])) (arr T U) *)
+
+(* prima dimostrare, poi perfezionare gli assiomi, poi dimostrarli *)
+
+axiom Judg_ind : βˆ€P:Env β†’ tm β†’ tp β†’ Prop.
+  (βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ P G (par X) T) β†’ 
+  (βˆ€G,M,N,T,U.
+    Judg G M (arr T U) β†’ Judg G N T β†’ 
+    P G M (arr T U) β†’ P G N T β†’ P G (app M N) U) β†’ 
+  (βˆ€G,T1,T2,X,M1.
+    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ Judg (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’
+    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ P (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’ 
+    P G (Lam X T1 (sctx_app M1 X)) (arr T1 T2)) β†’ 
+  βˆ€G,M,T.Judg G M T β†’ P G M T.
+
+axiom t_par : βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ Judg G (par X) T.
+axiom t_app2 : βˆ€G,M,N,T,U.Judg G M (arr T U) β†’ Judg G N T β†’ Judg G (app M N) U.
+axiom t_Lam : βˆ€G,X,M,T,U.Judg (〈X,TβŒͺ::G) M U β†’ Judg G (Lam X T M) (arr T U).
+
+definition subenv β‰ Ξ»G1,G2.βˆ€x.x β—ƒ G1 β†’ x β—ƒ G2.
+interpretation "subenv" 'subseteq G1 G2 = (subenv G1 G2).
+
+axiom daemon : βˆ€P:Prop.P.
+
+theorem weakening : βˆ€G1,G2,M,T.G1 βŠ† G2 β†’ Judg G1 M T β†’ Judg G2 M T.
+#G1 #G2 #M #T #Hsub #HJ lapply Hsub lapply G2 -G2 change with (βˆ€G2.?)
+@(Judg_ind β€¦ HJ)
+[ #X #G #T0 #Hin #G2 #Hsub @t_par @Hsub //
+| #G #M0 #N #T0 #U #HM0 #HN #IH1 #IH2 #G2 #Hsub @t_app2
+  [| @IH1 // | @IH2 // ]
+| #G #T1 #T2 #X #M1 #HM1 #IH #G2 #Hsub @t_Lam @IH 
+  [ (* trivial property of Lam *) @daemon 
+  | (* trivial property of subenv *) @daemon ]
+]
+qed.
+
+(* Serve un tipo Tm per i termini localmente chiusi e i suoi principi di induzione e
+   ricorsione *)
\ No newline at end of file
diff --git a/matita/matita/broken_lib/binding/ln_concrete.ma b/matita/matita/broken_lib/binding/ln_concrete.ma
new file mode 100644 (file)
index 0000000..bdafdb1
--- /dev/null
@@ -0,0 +1,683 @@
+(**************************************************************************)
+(*       ___                                                              *)
+(*      ||M||                                                             *)
+(*      ||A||       A project by Andrea Asperti                           *)
+(*      ||T||                                                             *)
+(*      ||I||       Developers:                                           *)
+(*      ||T||         The HELM team.                                      *)
+(*      ||A||         http://helm.cs.unibo.it                             *)
+(*      \   /                                                             *)
+(*       \ /        This file is distributed under the terms of the       *)
+(*        v         GNU General Public License Version 2                  *)
+(*                                                                        *)
+(**************************************************************************)
+
+include "basics/lists/list.ma".
+include "basics/deqsets.ma".
+include "binding/names.ma".
+include "binding/fp.ma".
+
+definition alpha : Nset β‰ X. check alpha
+notation "𝔸" non associative with precedence 90 for @{'alphabet}.
+interpretation "set of names" 'alphabet = alpha.
+
+inductive tp : Type[0] β‰ 
+| top : tp
+| arr : tp β†’ tp β†’ tp.
+inductive pretm : Type[0] β‰ 
+| var : nat β†’ pretm
+| par :  π”Έ β†’ pretm
+| abs : tp β†’ pretm β†’ pretm
+| app : pretm β†’ pretm β†’ pretm.
+
+let rec Nth T n (l:list T) on n β‰ 
+  match l with 
+  [ nil β‡’ None ?
+  | cons hd tl β‡’ match n with
+    [ O β‡’ Some ? hd
+    | S n0 β‡’ Nth T n0 tl ] ].
+
+let rec vclose_tm_aux u x k β‰ match u with
+  [ var n β‡’ if (leb k n) then var (S n) else u
+  | par x0 β‡’ if (x0 == x) then (var k) else u
+  | app v1 v2 β‡’ app (vclose_tm_aux v1 x k) (vclose_tm_aux v2 x k)
+  | abs s v β‡’ abs s (vclose_tm_aux v x (S k)) ].
+definition vclose_tm β‰ Ξ»u,x.vclose_tm_aux u x O.  
+
+definition vopen_var β‰ Ξ»n,x,k.match eqb n k with
+ [ true β‡’ par x
+ | false β‡’ match leb n k with
+   [ true β‡’ var n
+   | false β‡’ var (pred n) ] ].
+
+let rec vopen_tm_aux u x k β‰ match u with
+  [ var n β‡’ vopen_var n x k
+  | par x0 β‡’ u
+  | app v1 v2 β‡’ app (vopen_tm_aux v1 x k) (vopen_tm_aux v2 x k)
+  | abs s v β‡’ abs s (vopen_tm_aux v x (S k)) ].
+definition vopen_tm β‰ Ξ»u,x.vopen_tm_aux u x O.
+
+let rec FV u β‰ match u with 
+  [ par x β‡’ [x]
+  | app v1 v2 β‡’ FV v1@FV v2
+  | abs s v β‡’ FV v
+  | _ β‡’ [ ] ].  
+
+definition lam β‰ Ξ»x,s,u.abs s (vclose_tm u x).
+
+let rec Pi_map_tm p u on u β‰ match u with
+[ par x β‡’ par (p x)
+| var _ β‡’ u
+| app v1 v2 β‡’ app (Pi_map_tm p v1) (Pi_map_tm p v2)
+| abs s v β‡’ abs s (Pi_map_tm p v) ].
+
+interpretation "permutation of tm" 'middot p x = (Pi_map_tm p x).
+
+notation "hvbox(u⌈xβŒ‰)"
+  with precedence 45
+  for @{ 'open $u $x }.
+
+(*
+notation "hvbox(u⌈xβŒ‰)"
+  with precedence 45
+  for @{ 'open $u $x }.
+notation "❴ u β΅ x" non associative with precedence 90 for @{ 'open $u $x }.
+*)
+interpretation "ln term variable open" 'open u x = (vopen_tm u x).
+notation < "hvbox(Ξ½ x break . u)"
+ with precedence 20
+for @{'nu $x $u }.
+notation > "Ξ½ list1 x sep , . term 19 u" with precedence 20
+  for ${ fold right @{$u} rec acc @{'nu $x $acc)} }.
+interpretation "ln term variable close" 'nu x u = (vclose_tm u x).
+
+let rec tm_height u β‰ match u with
+[ app v1 v2 β‡’ S (max (tm_height v1) (tm_height v2))
+| abs s v β‡’ S (tm_height v) 
+| _ β‡’ O ].
+
+theorem le_n_O_rect_Type0 : βˆ€n:nat. n β‰€ O β†’ βˆ€P: nat β†’Type[0]. P O β†’ P n.
+#n (cases n) // #a #abs cases (?:False) /2/ qed. 
+
+theorem nat_rect_Type0_1 : βˆ€n:nat.βˆ€P:nat β†’ Type[0]. 
+(βˆ€m.(βˆ€p. p < m β†’ P p) β†’ P m) β†’ P n.
+#n #P #H 
+cut (βˆ€q:nat. q β‰€ n β†’ P q) /2/
+(elim n) 
+ [#q #HleO (* applica male *) 
+    @(le_n_O_rect_Type0 ? HleO)
+    @H #p #ltpO cases (?:False) /2/ (* 3 *)
+ |#p #Hind #q #HleS 
+    @H #a #lta @Hind @le_S_S_to_le /2/
+ ]
+qed.
+
+lemma leb_false_to_lt : βˆ€n,m. leb n m = false β†’ m < n.
+#n elim n
+[ #m normalize #H destruct(H)
+| #n0 #IH * // #m normalize #H @le_S_S @IH // ]
+qed.
+
+lemma nominal_eta_aux : βˆ€x,u.x βˆ‰ FV u β†’ βˆ€k.vclose_tm_aux (vopen_tm_aux u x k) x k = u.
+#x #u elim u
+[ #n #_ #k normalize cases (decidable_eq_nat n k) #Hnk
+  [ >Hnk >eqb_n_n whd in βŠ’ (??%?); >(\b ?) //
+  | >(not_eq_to_eqb_false β€¦ Hnk) normalize cases (true_or_false (leb n k)) #Hleb
+    [ >Hleb normalize >(?:leb k n = false) //
+      @lt_to_leb_false @not_eq_to_le_to_lt /2/
+    | >Hleb normalize >(?:leb k (pred n) = true) normalize
+      [ cases (leb_false_to_lt β€¦ Hleb) //
+      | @le_to_leb_true cases (leb_false_to_lt β€¦ Hleb) normalize /2/ ] ] ]
+| #y normalize in βŠ’ (%β†’?β†’?); #Hy whd in βŠ’ (?β†’??%?); >(\bf ?) // @(not_to_not β€¦ Hy) //
+| #s #v #IH normalize #Hv #k >IH // @Hv
+| #v1 #v2 #IH1 #IH2 normalize #Hv1v2 #k 
+  >IH1 [ >IH2 // | @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_l ]
+  @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_r ]
+qed.
+
+corollary nominal_eta : βˆ€x,u.x βˆ‰ FV u β†’ (Ξ½x.u⌈xβŒ‰) = u.
+#x #u #Hu @nominal_eta_aux //
+qed.
+
+lemma eq_height_vopen_aux : βˆ€v,x,k.tm_height (vopen_tm_aux v x k) = tm_height v.
+#v #x elim v
+[ #n #k normalize cases (eqb n k) // cases (leb n k) //
+| #u #k %
+| #s #u #IH #k normalize >IH %
+| #u1 #u2 #IH1 #IH2 #k normalize >IH1 >IH2 % ]
+qed.
+
+corollary eq_height_vopen : βˆ€v,x.tm_height (v⌈xβŒ‰) = tm_height v.
+#v #x @eq_height_vopen_aux
+qed.
+
+theorem pretm_ind_plus_aux : 
+ βˆ€P:pretm β†’ Type[0].
+   (βˆ€x:𝔸.P (par x)) β†’ 
+   (βˆ€n:β„•.P (var n)) β†’ 
+   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
+ βˆ€n,u.tm_height u β‰€ n β†’ P u.
+#P #Hpar #Hvar #Happ #C #Hlam #n change with ((Ξ»n.?) n); @(nat_rect_Type0_1 n ??)
+#m cases m
+[ #_ * /2/
+  [ normalize #s #v #Hfalse cases (?:False) cases (not_le_Sn_O (tm_height v)) /2/
+  | #v1 #v2 whd in βŠ’ (?%?β†’?); #Hfalse cases (?:False) cases (not_le_Sn_O (S (max ??))) /2/ ] ]
+-m #m #IH * /2/
+[ #s #v whd in βŠ’ (?%?β†’?); #Hv
+  lapply (p_fresh β€¦ (C@FV v)) letin y β‰ (N_fresh β€¦ (C@FV v)) #Hy
+  >(?:abs s v = lam y s (v⌈yβŒ‰))
+  [| whd in βŠ’ (???%); >nominal_eta // @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r ] 
+  @Hlam
+  [ @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r
+  | @(not_to_not β€¦ Hy) @in_list_to_in_list_append_l ]
+  @IH [| @Hv | >eq_height_vopen % ]
+| #v1 #v2 whd in βŠ’ (?%?β†’?); #Hv @Happ
+  [ @IH [| @Hv | // ] | @IH [| @Hv | // ] ] ]
+qed.
+
+corollary pretm_ind_plus :
+ βˆ€P:pretm β†’ Type[0].
+   (βˆ€x:𝔸.P (par x)) β†’ 
+   (βˆ€n:β„•.P (var n)) β†’ 
+   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
+ βˆ€u.P u.
+#P #Hpar #Hvar #Happ #C #Hlam #u @pretm_ind_plus_aux /2/
+qed.
+
+(* maps a permutation to a list of terms *)
+definition Pi_map_list : (𝔸 β†’ π”Έ) β†’ list π”Έ β†’ list π”Έ β‰ map π”Έ π”Έ .
+
+(* interpretation "permutation of name list" 'middot p x = (Pi_map_list p x).*)
+
+(*
+inductive tm : pretm β†’ Prop β‰ 
+| tm_par : βˆ€x:𝔸.tm (par x)
+| tm_app : βˆ€u,v.tm u β†’ tm v β†’ tm (app u v)
+| tm_lam : βˆ€x,s,u.tm u β†’ tm (lam x s u).
+
+inductive ctx_aux : nat β†’ pretm β†’ Prop β‰ 
+| ctx_var : βˆ€n,k.n < k β†’ ctx_aux k (var n)
+| ctx_par : βˆ€x,k.ctx_aux k (par x)
+| ctx_app : βˆ€u,v,k.ctx_aux k u β†’ ctx_aux k v β†’ ctx_aux k (app u v)
+(* Γ¨ sostituibile da ctx_lam ? *)
+| ctx_abs : βˆ€s,u.ctx_aux (S k) u β†’ ctx_aux k (abs s u).
+*)
+
+inductive tm_or_ctx (k:nat) : pretm β†’ Type[0] β‰ 
+| toc_var : βˆ€n.n < k β†’ tm_or_ctx k (var n)
+| toc_par : βˆ€x.tm_or_ctx k (par x)
+| toc_app : βˆ€u,v.tm_or_ctx k u β†’ tm_or_ctx k v β†’ tm_or_ctx k (app u v)
+| toc_lam : βˆ€x,s,u.tm_or_ctx k u β†’ tm_or_ctx k (lam x s u).
+
+definition tm β‰ Ξ»t.tm_or_ctx O t.
+definition ctx β‰ Ξ»t.tm_or_ctx 1 t.
+
+record TM : Type[0] β‰ {
+  pretm_of_TM :> pretm;
+  tm_of_TM : tm pretm_of_TM
+}.
+
+record CTX : Type[0] β‰ {
+  pretm_of_CTX :> pretm;
+  ctx_of_CTX : ctx pretm_of_CTX
+}.
+
+inductive tm2 : pretm β†’ Type[0] β‰ 
+| tm_par : βˆ€x.tm2 (par x)
+| tm_app : βˆ€u,v.tm2 u β†’ tm2 v β†’ tm2 (app u v)
+| tm_lam : βˆ€x,s,u.x βˆ‰ FV u β†’ (βˆ€y.y βˆ‰ FV u β†’ tm2 (u⌈yβŒ‰)) β†’ tm2 (lam x s (u⌈xβŒ‰)).
+
+(*
+inductive tm' : pretm β†’ Prop β‰ 
+| tm_par : βˆ€x.tm' (par x)
+| tm_app : βˆ€u,v.tm' u β†’ tm' v β†’ tm' (app u v)
+| tm_lam : βˆ€x,s,u,C.x βˆ‰ FV u β†’ x βˆ‰ C β†’ (βˆ€y.y βˆ‰ FV u β†’ tm' (❴u❡y)) β†’ tm' (lam x s (❴u❡x)).
+*)
+
+axiom swap_inj : βˆ€N.βˆ€z1,z2,x,y.swap N z1 z2 x = swap N z1 z2 y β†’ x = y.
+
+lemma pi_vclose_tm : 
+  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(Ξ½x.u) = (Ξ½ swap ? z1 z2 x.swap π”Έ z1 z2 Β· u).
+#z1 #z2 #x #u
+change with (vclose_tm_aux ???) in match (vclose_tm ??);
+change with (vclose_tm_aux ???) in βŠ’ (???%); lapply O elim u
+[3:whd in βŠ’ (?β†’?β†’(?β†’ ??%%)β†’?β†’??%%); //
+|4:whd in βŠ’ (?β†’?β†’(?β†’??%%)β†’(?β†’??%%)β†’?β†’??%%); //
+| #n #k whd in βŠ’ (??(??%)%); cases (leb k n) normalize %
+| #x0 #k cases (true_or_false (x0==z1)) #H1 >H1 whd in βŠ’ (??%%);
+  [ cases (true_or_false (x0==x)) #H2 >H2 whd in βŠ’ (??(??%)%);
+    [ <(\P H2) >H1 whd in βŠ’ (??(??%)%); >(\b ?) // >(\b ?) //
+    | >H2 whd in match (swap ????); >H1
+      whd in match (if false then var k else ?);
+      whd in match (if true then z2 else ?); >(\bf ?)
+      [ >(\P H1) >swap_left %
+      | <(swap_inv ? z1 z2 z2) in βŠ’ (?(??%?)); % #H3
+        lapply (swap_inj β€¦ H3) >swap_right #H4 <H4 in H2; >H1 #H destruct (H) ]
+    ]
+  | >(?:(swap ? z1 z2 x0 == swap ? z1 z2 x) = (x0 == x))
+    [| cases (true_or_false (x0==x)) #H2 >H2
+      [ >(\P H2) @(\b ?) %
+      | @(\bf ?) % #H >(swap_inj β€¦ H) in H2; >(\b ?) // #H0 destruct (H0) ] ]
+    cases (true_or_false (x0==x)) #H2 >H2 whd in βŠ’ (??(??%)%); 
+    [ <(\P H2) >H1 >(\b (refl ??)) %
+    | >H1 >H2 % ]
+    ]
+  ]
+qed.
+
+lemma pi_vopen_tm : 
+  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(u⌈xβŒ‰) = (swap π”Έ z1 z2 Β· u⌈swap π”Έ z1 z2 xβŒ‰).
+#z1 #z2 #x #u
+change with (vopen_tm_aux ???) in match (vopen_tm ??);
+change with (vopen_tm_aux ???) in βŠ’ (???%); lapply O elim u //
+[2: #s #v whd in βŠ’ ((?β†’??%%)β†’?β†’??%%); //
+|3: #v1 #v2 whd in βŠ’ ((?β†’??%%)β†’(?β†’??%%)β†’?β†’??%%); /2/ ]
+#n #k whd in βŠ’ (??(??%)%); cases (true_or_false (eqb n k)) #H1 >H1 //
+cases (true_or_false (leb n k)) #H2 >H2 normalize //
+qed.
+
+lemma pi_lam : 
+  βˆ€z1,z2,x,s,u.swap π”Έ z1 z2 Β· lam x s u = lam (swap π”Έ z1 z2 x) s (swap π”Έ z1 z2 Β· u).
+#z1 #z2 #x #s #u whd in βŠ’ (???%); <(pi_vclose_tm β€¦) %
+qed.
+
+lemma eqv_FV : βˆ€z1,z2,u.FV (swap π”Έ z1 z2 Β· u) = Pi_map_list (swap π”Έ z1 z2) (FV u).
+#z1 #z2 #u elim u //
+[ #s #v #H @H
+| #v1 #v2 whd in βŠ’ (??%%β†’??%%β†’??%%); #H1 #H2 >H1 >H2
+  whd in βŠ’ (???(????%)); /2/ ]
+qed.
+
+lemma swap_inv_tm : βˆ€z1,z2,u.swap π”Έ z1 z2 Β· (swap π”Έ z1 z2 Β· u) = u.
+#z1 #z2 #u elim u 
+[1: #n %
+|3: #s #v whd in βŠ’ (?β†’??%%); //
+|4: #v1 #v2 #Hv1 #Hv2 whd in βŠ’ (??%%); // ]
+#x whd in βŠ’ (??%?); >swap_inv %
+qed.
+
+lemma eqv_in_list : βˆ€x,l,z1,z2.x βˆˆ l β†’ swap π”Έ z1 z2 x βˆˆ Pi_map_list (swap π”Έ z1 z2) l.
+#x #l #z1 #z2 #Hin elim Hin
+[ #x0 #l0 %
+| #x1 #x2 #l0 #Hin #IH %2 @IH ]
+qed.
+
+lemma eqv_tm2 : βˆ€u.tm2 u β†’ βˆ€z1,z2.tm2 ((swap ? z1 z2)Β·u).
+#u #Hu #z1 #z2 letin p β‰ (swap ? z1 z2) elim Hu /2/
+#x #s #v #Hx #Hv #IH >pi_lam >pi_vopen_tm %3
+[ @(not_to_not β€¦ Hx) -Hx #Hx
+  <(swap_inv ? z1 z2 x) <(swap_inv_tm z1 z2 v) >eqv_FV @eqv_in_list //
+| #y #Hy <(swap_inv ? z1 z2 y)
+  <pi_vopen_tm @IH @(not_to_not β€¦ Hy) -Hy #Hy <(swap_inv ? z1 z2 y)
+  >eqv_FV @eqv_in_list //
+]
+qed.
+
+lemma vclose_vopen_aux : βˆ€x,u,k.vopen_tm_aux (vclose_tm_aux u x k) x k = u.
+#x #u elim u [1,3,4:normalize //]
+[ #n #k cases (true_or_false (leb k n)) #H >H whd in βŠ’ (??%?);
+  [ cases (true_or_false (eqb (S n) k)) #H1 >H1
+    [ <(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_true_to_le β€¦ H) -H #H
+      cases (le_to_not_lt β€¦ H) -H #H cases (H ?) %
+    | whd in βŠ’ (??%?); >lt_to_leb_false // @le_S_S /2/ ]
+  | cases (true_or_false (eqb n k)) #H1 >H1 normalize
+    [ >(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_false_to_not_le β€¦ H) -H
+      * #H cases (H ?) %
+    | >le_to_leb_true // @not_lt_to_le % #H2 >le_to_leb_true in H;
+      [ #H destruct (H) | /2/ ]
+    ]
+  ]
+| #x0 #k whd in βŠ’ (??(?%??)?); cases (true_or_false (x0==x)) 
+  #H1 >H1 normalize // >(\P H1) >eqb_n_n % ]
+qed.      
+
+lemma vclose_vopen : βˆ€x,u.((Ξ½x.u)⌈xβŒ‰) = u. #x #u @vclose_vopen_aux
+qed.
+
+(*
+theorem tm_to_tm : βˆ€t.tm' t β†’ tm t.
+#t #H elim H
+*)
+
+lemma in_list_singleton : βˆ€T.βˆ€t1,t2:T.t1 βˆˆ [t2] β†’ t1 = t2.
+#T #t1 #t2 #H @(in_list_inv_ind ??? H) /2/
+qed.
+
+lemma fresh_vclose_tm_aux : βˆ€u,x,k.x βˆ‰ FV (vclose_tm_aux u x k).
+#u #x elim u //
+[ #n #k normalize cases (leb k n) normalize //
+| #x0 #k whd in βŠ’ (?(???(?%))); cases (true_or_false (x0==x)) #H >H normalize //
+  lapply (\Pf H) @not_to_not #Hin >(in_list_singleton ??? Hin) %
+| #v1 #v2 #IH1 #IH2 #k normalize % #Hin cases (in_list_append_to_or_in_list ???? Hin) -Hin #Hin
+  [ cases (IH1 k) -IH1 #IH1 @IH1 @Hin | cases (IH2 k) -IH2 #IH2 @IH2 @Hin ]
+qed.
+
+lemma fresh_vclose_tm : βˆ€u,x.x βˆ‰ FV (Ξ½x.u). //
+qed.
+
+lemma fresh_swap_tm : βˆ€z1,z2,u.z1 βˆ‰ FV u β†’ z2 βˆ‰ FV u β†’ swap π”Έ z1 z2 Β· u = u.
+#z1 #z2 #u elim u
+[2: normalize in βŠ’ (?β†’%β†’%β†’?); #x #Hz1 #Hz2 whd in βŠ’ (??%?); >swap_other //
+  [ @(not_to_not β€¦ Hz2) | @(not_to_not β€¦ Hz1) ] //
+|1: //
+| #s #v #IH normalize #Hz1 #Hz2 >IH // [@Hz2|@Hz1]
+| #v1 #v2 #IH1 #IH2 normalize #Hz1 #Hz2
+  >IH1 [| @(not_to_not β€¦ Hz2) @in_list_to_in_list_append_l | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_l ]
+  >IH2 // [@(not_to_not β€¦ Hz2) @in_list_to_in_list_append_r | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_r ]
+]
+qed.
+
+theorem tm_to_tm2 : βˆ€u.tm u β†’ tm2 u.
+#t #Ht elim Ht
+[ #n #Hn cases (not_le_Sn_O n) #Hfalse cases (Hfalse Hn)
+| @tm_par
+| #u #v #Hu #Hv @tm_app
+| #x #s #u #Hu #IHu <(vclose_vopen x u) @tm_lam
+  [ @fresh_vclose_tm
+  | #y #Hy <(fresh_swap_tm x y (Ξ½x.u)) /2/ @fresh_vclose_tm ]
+]
+qed.
+
+theorem tm2_to_tm : βˆ€u.tm2 u β†’ tm u.
+#u #pu elim pu /2/ #x #s #v #Hx #Hv #IH %4 @IH //
+qed.
+
+definition PAR β‰ Ξ»x.mk_TM (par x) ?. // qed.
+definition APP β‰ Ξ»u,v:TM.mk_TM (app u v) ?./2/ qed.
+definition LAM β‰ Ξ»x,s.Ξ»u:TM.mk_TM (lam x s u) ?./2/ qed.
+
+axiom vopen_tm_down : βˆ€u,x,k.tm_or_ctx (S k) u β†’ tm_or_ctx k (u⌈xβŒ‰).
+(* needs true_plus_false
+
+#u #x #k #Hu elim Hu
+[ #n #Hn normalize cases (true_or_false (eqb n O)) #H >H [%2]
+  normalize >(?: leb n O = false) [|cases n in H; // >eqb_n_n #H destruct (H) ]
+  normalize lapply Hn cases n in H; normalize [ #Hfalse destruct (Hfalse) ]
+  #n0 #_ #Hn0 % @le_S_S_to_le //
+| #x0 %2
+| #v1 #v2 #Hv1 #Hv2 #IH1 #IH2 %3 //
+| #x0 #s #v #Hv #IH normalize @daemon
+]
+qed.
+*)
+
+definition vopen_TM β‰ Ξ»u:CTX.Ξ»x.mk_TM (u⌈xβŒ‰) (vopen_tm_down β€¦). @ctx_of_CTX qed.
+
+axiom vclose_tm_up : βˆ€u,x,k.tm_or_ctx k u β†’ tm_or_ctx (S k) (Ξ½x.u).
+
+definition vclose_TM β‰ Ξ»u:TM.Ξ»x.mk_CTX (Ξ½x.u) (vclose_tm_up β€¦). @tm_of_TM qed.
+
+interpretation "ln wf term variable open" 'open u x = (vopen_TM u x).
+interpretation "ln wf term variable close" 'nu x u = (vclose_TM u x).
+
+theorem tm_alpha : βˆ€x,y,s,u.x βˆ‰ FV u β†’ y βˆ‰ FV u β†’ lam x s (u⌈xβŒ‰) = lam y s (u⌈yβŒ‰).
+#x #y #s #u #Hx #Hy whd in βŠ’ (??%%); @eq_f >nominal_eta // >nominal_eta //
+qed.
+
+theorem TM_ind_plus : 
+(* non si puΓ² dare il principio in modo dipendente (almeno utilizzando tm2)
+   la "prova" purtroppo Γ¨ in Type e non si puΓ² garantire che sia esattamente
+   quella che ci aspetteremmo
+ *)
+ βˆ€P:pretm β†’ Type[0].
+   (βˆ€x:𝔸.P (PAR x)) β†’ 
+   (βˆ€v1,v2:TM.P v1 β†’ P v2 β†’ P (APP v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s.βˆ€v:CTX.x βˆ‰ FV v β†’ x βˆ‰ C β†’ 
+     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (LAM x s (v⌈xβŒ‰))) β†’
+ βˆ€u:TM.P u.
+#P #Hpar #Happ #C #Hlam * #u #pu elim (tm_to_tm2 u pu) //
+[ #v1 #v2 #pv1 #pv2 #IH1 #IH2 @(Happ (mk_TM β€¦) (mk_TM β€¦)) /2/
+| #x #s #v #Hx #pv #IH
+  lapply (p_fresh β€¦ (C@FV v)) letin x0 β‰ (N_fresh β€¦ (C@FV v)) #Hx0
+  >(?:lam x s (v⌈xβŒ‰) = lam x0 s (v⌈x0βŒ‰))
+  [|@tm_alpha // @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r ]
+  @(Hlam x0 s (mk_CTX v ?) ??)
+  [ <(nominal_eta β€¦ Hx) @vclose_tm_up @tm2_to_tm @pv //
+  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r
+  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_l
+  | @IH ]
+]
+qed.
+
+notation 
+"hvbox('nominal' u 'return' out 'with' 
+       [ 'xpar' ident x β‡’ f1 
+       | 'xapp' ident v1 ident v2 ident recv1 ident recv2 β‡’ f2 
+       | 'xlam' β¨ident y # C❩ ident s ident w ident py1 ident py2 ident recw β‡’ f3 ])"
+with precedence 48 
+for @{ TM_ind_plus $out (Ξ»${ident x}:?.$f1)
+       (Ξ»${ident v1}:?.Ξ»${ident v2}:?.Ξ»${ident recv1}:?.Ξ»${ident recv2}:?.$f2)
+       $C (Ξ»${ident y}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.Ξ»${ident recw}:?.$f3)
+       $u }.
+       
+(* include "basics/jmeq.ma".*)
+
+definition subst β‰ (Ξ»u:TM.Ξ»x,v.
+  nominal u return (Ξ»_.TM) with 
+  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ u ]
+  | xapp v1 v2 recv1 recv2 β‡’ APP recv1 recv2
+  | xlam β¨y # x::FV v❩ s w py1 py2 recw β‡’ LAM y s (recw y py1) ]).
+
+lemma fasfd : βˆ€s,v. pretm_of_TM (subst (LAM O s (PAR 1)) O v) = pretm_of_TM (LAM O s (PAR 1)).
+#s #v normalize in βŠ’ (??%?);
+
+
+theorem tm2_ind_plus : 
+(* non si puΓ² dare il principio in modo dipendente (almeno utilizzando tm2) *)
+ βˆ€P:pretm β†’ Type[0].
+   (βˆ€x:𝔸.P (par x)) β†’ 
+   (βˆ€v1,v2.tm2 v1 β†’ tm2 v2 β†’ P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
+   βˆ€C:list π”Έ.
+   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ (βˆ€y.y βˆ‰ FV v β†’ tm2 (v⌈yβŒ‰)) β†’ 
+     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (lam x s (v⌈xβŒ‰))) β†’
+ βˆ€u.tm2 u β†’ P u.
+#P #Hpar #Happ #C #Hlam #u #pu elim pu /2/
+#x #s #v #px #pv #IH 
+lapply (p_fresh β€¦ (C@FV v)) letin y β‰ (N_fresh β€¦ (C@FV v)) #Hy
+>(?:lam x s (v⌈xβŒ‰) = lam y s (v⌈yβŒ‰)) [| @tm_alpha // @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r ]
+@Hlam /2/ lapply Hy -Hy @not_to_not #Hy
+[ @in_list_to_in_list_append_r @Hy | @in_list_to_in_list_append_l @Hy ]
+qed.
+
+definition check_tm β‰ 
+  Ξ»u.pretm_ind_plus ? (Ξ»_.true) (Ξ»_.false) 
+    (Ξ»v1,v2,r1,r2.r1 βˆ§ r2) [ ] (Ξ»x,s,v,pv1,pv2,rv.rv) u.
+
+(*
+lemma check_tm_complete : βˆ€u.tm u β†’ check_tm u = true.
+#u #pu @(tm2_ind_plus β€¦ [ ] β€¦ (tm_to_tm2 ? pu)) //
+[ #v1 #v2 #pv1 #pv2 #IH1 #IH2
+| #x #s #v #Hx1 #Hx2 #Hv #IH
+*)
+
+notation 
+"hvbox('nominal' u 'return' out 'with' 
+       [ 'xpar' ident x β‡’ f1 
+       | 'xapp' ident v1 ident v2 ident pv1 ident pv2 ident recv1 ident recv2 β‡’ f2 
+       | 'xlam' β¨ident y # C❩ ident s ident w ident py1 ident py2 ident pw ident recw β‡’ f3 ])"
+with precedence 48 
+for @{ tm2_ind_plus $out (Ξ»${ident x}:?.$f1)
+       (Ξ»${ident v1}:?.Ξ»${ident v2}:?.Ξ»${ident pv1}:?.Ξ»${ident pv2}:?.Ξ»${ident recv1}:?.Ξ»${ident recv2}:?.$f2)
+       $C (Ξ»${ident y}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.Ξ»${ident pw}:?.Ξ»${ident recw}:?.$f3)
+       ? (tm_to_tm2 ? $u) }.
+(* notation 
+"hvbox('nominal' u 'with' 
+       [ 'xlam' ident x # C ident s ident w β‡’ f3 ])"
+with precedence 48 
+for @{ tm2_ind_plus ???
+ $C (Ξ»${ident x}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.
+     Ξ»${ident pw}:?.Ξ»${ident recw}:?.$f3) $u (tm_to_tm2 ??) }.
+*)
+
+
+definition subst β‰ (Ξ»u.Ξ»pu:tm u.Ξ»x,v.
+  nominal pu return (Ξ»_.pretm) with 
+  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ u ]
+  | xapp v1 v2 pv1 pv2 recv1 recv2 β‡’ app recv1 recv2
+  | xlam β¨y # x::FV v❩ s w py1 py2 pw recw β‡’ lam y s (recw y py1) ]).
+  
+lemma fasfd : βˆ€x,s,u,p1,v. subst (lam x s u) p1 x v = lam x s u.
+#x #s #u #p1 #v
+
+
+definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,y.
+  tm2_ind_plus ?
+  (* par x0 *)              (Ξ»x0.match x == x0 with [ true β‡’ v | false β‡’ u ])
+  (* app v1 v2 *)           (Ξ»v1,v2,pv1,pv2,recv1,recv2.app recv1 recv2)
+  (* lam y#(x::FV v) s w *) (x::FV v) (Ξ»y,s,w,py1,py2,pw,recw.lam y s (recw y py1)) 
+  u (tm_to_tm2 β€¦ pu).
+check subst
+definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,v.
+  nominal u with 
+  [ xlam y # (x::FV v) s w ^ ? ].
+
+(*
+notation > "Ξ› ident x. ident T [ident x] β†¦ P"
+  with precedence 48 for @{'foo (Ξ»${ident x}.Ξ»${ident T}.$P)}.
+
+notation < "Ξ› ident x. ident T [ident x] β†¦ P"
+  with precedence 48 for @{'foo (Ξ»${ident x}:$Q.Ξ»${ident T}:$R.$P)}.
+*)
+
+(*
+notation 
+"hvbox('nominal' u 'with' 
+       [ 'xpar' ident x β‡’ f1 
+       | 'xapp' ident v1 ident v2  β‡’ f2
+       | 'xlam' ident x # C s w β‡’ f3 ])"
+with precedence 48 
+for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
+ (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
+ $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
+*)
+
+(*
+notation 
+"hvbox('nominal' u 'with' 
+       [ 'xpar' ident x ^ f1 
+       | 'xapp' ident v1 ident v2 ^ f2 ])"
+(*       | 'xlam' ident x # C s w ^ f3 ]) *)
+with precedence 48 
+for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
+ (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
+ $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
+*)
+notation 
+"hvbox('nominal' u 'with' 
+       [ 'xpar' ident x ^ f1 
+       | 'xapp' ident v1 ident v2 ^ f2 ])"
+with precedence 48 
+for @{ tm2_ind_plus ? (Ξ»${ident x}:?.$f1) 
+ (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
+ $C (Ξ»${ident x}:?.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
+
+
+definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,v.
+  nominal u with 
+  [ xpar x0 ^ match x == x0 with [ true β‡’ v | false β‡’ u ]
+  | xapp v1 v2 ^ ? ].
+  | xlam y # (x::FV v) s w ^ ? ].
+  
+  
+  (* par x0 *)              (Ξ»x0.match x == x0 with [ true β‡’ v | false β‡’ u ])
+  (* app v1 v2 *)           (Ξ»v1,v2,pv1,pv2,recv1,recv2.app recv1 recv2)
+  (* lam y#(x::FV v) s w *) (x::FV v) (Ξ»y,s,w,py1,py2,pw,recw.lam y s (recw y py1)) 
+  u (tm_to_tm2 β€¦ pu).
+*)
+definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,v.
+  tm2_ind_plus ?
+  (* par x0 *)              (Ξ»x0.match x == x0 with [ true β‡’ v | false β‡’ u ])
+  (* app v1 v2 *)           (Ξ»v1,v2,pv1,pv2,recv1,recv2.app recv1 recv2)
+  (* lam y#(x::FV v) s w *) (x::FV v) (Ξ»y,s,w,py1,py2,pw,recw.lam y s (recw y py1)) 
+  u (tm_to_tm2 β€¦ pu).
+
+check subst
+
+axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
+notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
+interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
+
+
+
+inductive judg : list tp β†’ tm β†’ tp β†’ Prop β‰ 
+| t_var : βˆ€g,n,t.Nth ? n g = Some ? t β†’ judg g (var n) t
+| t_app : βˆ€g,m,n,t,u.judg g m (arr t u) β†’ judg g n t β†’ judg g (app m n) u
+| t_abs : βˆ€g,t,m,u.judg (t::g) m u β†’ judg g (abs t m) (arr t u).
+
+definition Env := list (𝔸 Γ— tp).
+
+axiom vclose_env : Env β†’ list tp.
+axiom vclose_tm : Env β†’ tm β†’ tm.
+axiom Lam : π”Έ β†’ tp β†’ tm β†’ tm.
+definition Judg β‰ Ξ»G,M,T.judg (vclose_env G) (vclose_tm G M) T.
+definition dom β‰ Ξ»G:Env.map ?? (fst ??) G.
+
+definition sctx β‰ π”Έ Γ— tm.
+axiom swap_tm : π”Έ β†’ π”Έ β†’ tm β†’ tm.
+definition sctx_app : sctx β†’ π”Έ β†’ tm β‰ Ξ»M0,Y.let βŒ©X,MβŒͺ β‰ M0 in swap_tm X Y M.
+
+axiom in_list : βˆ€A:Type[0].A β†’ list A β†’ Prop.
+interpretation "list membership" 'mem x l = (in_list ? x l).
+interpretation "list non-membership" 'notmem x l = (Not (in_list ? x l)).
+
+axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
+notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
+interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
+
+let rec FV M β‰ match M with 
+  [ par X β‡’ [X]
+  | app M1 M2 β‡’ FV M1@FV M2
+  | abs T M0 β‡’ FV M0
+  | _ β‡’ [ ] ].
+
+(* axiom Lookup : π”Έ β†’ Env β†’ option tp. *)
+
+(* forma alto livello del judgment
+   t_abs* : βˆ€G,T,X,M,U.
+            (βˆ€Y βˆ‰ supp(M).Judg (〈Y,TβŒͺ::G) (M[Y]) U) β†’ 
+            Judg G (Lam X T (M[X])) (arr T U) *)
+
+(* prima dimostrare, poi perfezionare gli assiomi, poi dimostrarli *)
+
+axiom Judg_ind : βˆ€P:Env β†’ tm β†’ tp β†’ Prop.
+  (βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ P G (par X) T) β†’ 
+  (βˆ€G,M,N,T,U.
+    Judg G M (arr T U) β†’ Judg G N T β†’ 
+    P G M (arr T U) β†’ P G N T β†’ P G (app M N) U) β†’ 
+  (βˆ€G,T1,T2,X,M1.
+    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ Judg (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’
+    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ P (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’ 
+    P G (Lam X T1 (sctx_app M1 X)) (arr T1 T2)) β†’ 
+  βˆ€G,M,T.Judg G M T β†’ P G M T.
+
+axiom t_par : βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ Judg G (par X) T.
+axiom t_app2 : βˆ€G,M,N,T,U.Judg G M (arr T U) β†’ Judg G N T β†’ Judg G (app M N) U.
+axiom t_Lam : βˆ€G,X,M,T,U.Judg (〈X,TβŒͺ::G) M U β†’ Judg G (Lam X T M) (arr T U).
+
+definition subenv β‰ Ξ»G1,G2.βˆ€x.x β—ƒ G1 β†’ x β—ƒ G2.
+interpretation "subenv" 'subseteq G1 G2 = (subenv G1 G2).
+
+axiom daemon : βˆ€P:Prop.P.
+
+theorem weakening : βˆ€G1,G2,M,T.G1 βŠ† G2 β†’ Judg G1 M T β†’ Judg G2 M T.
+#G1 #G2 #M #T #Hsub #HJ lapply Hsub lapply G2 -G2 change with (βˆ€G2.?)
+@(Judg_ind β€¦ HJ)
+[ #X #G #T0 #Hin #G2 #Hsub @t_par @Hsub //
+| #G #M0 #N #T0 #U #HM0 #HN #IH1 #IH2 #G2 #Hsub @t_app2
+  [| @IH1 // | @IH2 // ]
+| #G #T1 #T2 #X #M1 #HM1 #IH #G2 #Hsub @t_Lam @IH 
+  [ (* trivial property of Lam *) @daemon 
+  | (* trivial property of subenv *) @daemon ]
+]
+qed.
+
+(* Serve un tipo Tm per i termini localmente chiusi e i suoi principi di induzione e
+   ricorsione *)
\ No newline at end of file
diff --git a/matita/matita/broken_lib/binding/names.ma b/matita/matita/broken_lib/binding/names.ma
new file mode 100644 (file)
index 0000000..bc5f07d
--- /dev/null
@@ -0,0 +1,78 @@
+(**************************************************************************)
+(*       ___                                                              *)
+(*      ||M||                                                             *)
+(*      ||A||       A project by Andrea Asperti                           *)
+(*      ||T||                                                             *)
+(*      ||I||       Developers:                                           *)
+(*      ||T||         The HELM team.                                      *)
+(*      ||A||         http://helm.cs.unibo.it                             *)
+(*      \   /                                                             *)
+(*       \ /        This file is distributed under the terms of the       *)
+(*        v         GNU General Public License Version 2                  *)
+(*                                                                        *)
+(**************************************************************************)
+
+include "basics/logic.ma".
+include "basics/lists/in.ma".
+include "basics/types.ma".
+
+(*interpretation "list membership" 'mem x l = (in_list ? x l).*)
+
+record Nset : Type[1] β‰
+{
+  (* carrier is specified as a coercion: when an object X of type Nset is
+     given, but something of type Type is expected, Matita will insert a
+     hidden coercion: the user sees "X", but really means "carrier X"     *)
+  carrier :> DeqSet;
+  N_fresh : list carrier β†’ carrier;
+  p_fresh : βˆ€l.N_fresh l βˆ‰ l
+}.
+
+definition maxlist β‰
+ Ξ»l.foldr ?? (Ξ»x,acc.max x acc) 0 l.
+
+definition natfresh β‰ Ξ»l.S (maxlist l).
+
+lemma le_max_1 : βˆ€x,y.x β‰€ max x y. /2/
+qed.
+
+lemma le_max_2 : βˆ€x,y.y β‰€ max x y. /2/
+qed.
+
+lemma le_maxlist : βˆ€l,x.x βˆˆ l β†’ x β‰€ maxlist l.
+#l elim l
+[#x #Hx @False_ind cases (not_in_list_nil ? x) #H1 /2/
+|#y #tl #IH #x #H1 change with (max ??) in βŠ’ (??%);
+ cases (in_list_cons_case ???? H1);#H2;
+ [ >H2 @le_max_1
+ | whd in βŠ’ (??%); lapply (refl ? (leb y (maxlist tl)));
+   cases (leb y (maxlist tl)) in βŠ’ (???% β†’ %);#H3
+   [ @IH //
+   | lapply (IH ? H2) #H4
+     lapply (leb_false_to_not_le β€¦ H3) #H5
+     lapply (not_le_to_lt β€¦ H5) #H6
+     @(transitive_le β€¦ H4)
+     @(transitive_le β€¦ H6) %2 %
+   ]
+ ]
+]
+qed.
+
+(* prove freshness for nat *)
+lemma lt_l_natfresh_l : βˆ€l,x.x βˆˆ l β†’ x < natfresh l.
+#l #x #H1 @le_S_S /2/
+qed.
+
+(*naxiom p_Xfresh : βˆ€l.βˆ€x:Xcarr.x βˆˆ l β†’ x β‰  ntm (Xfresh l) βˆ§ x β‰  ntp (Xfresh l).*)
+lemma p_natfresh : βˆ€l.natfresh l βˆ‰ l.
+#l % #H1 lapply (lt_l_natfresh_l β€¦ H1) #H2
+cases (lt_to_not_eq β€¦ H2) #H3 @H3 %
+qed.
+
+include "basics/finset.ma".
+
+definition X : Nset β‰ mk_Nset DeqNat β€¦.
+[ @natfresh
+| @p_natfresh
+]
+qed.
\ No newline at end of file
diff --git a/matita/matita/broken_lib/finite_lambda/confluence.ma b/matita/matita/broken_lib/finite_lambda/confluence.ma
new file mode 100644 (file)
index 0000000..32b7e3f
--- /dev/null
@@ -0,0 +1,226 @@
+(*
+    ||M||  This file is part of HELM, an Hypertextual, Electronic        
+    ||A||  Library of Mathematics, developed at the Computer Science     
+    ||T||  Department of the University of Bologna, Italy.                     
+    ||I||                                                                 
+    ||T||  
+    ||A||  This file is distributed under the terms of the 
+    \   /  GNU General Public License Version 2        
+     \ /      
+      V_______________________________________________________________ *)
+
+include "finite_lambda/reduction.ma".
+
+   
+axiom canonical_to_T: βˆ€O,D.βˆ€M:T O D.βˆ€ty.(* type_of M ty β†’ *)
+  βˆƒa:FinSet_of_FType O D ty. star ? (red O D) M (to_T O D ty a).
+   
+axiom normal_to_T: βˆ€O,D,M,ty,a. red O D (to_T O D ty a) M β†’ False.
+
+axiom red_closed: βˆ€O,D,M,M1. 
+  is_closed O D 0 M β†’ red O D M M1 β†’ is_closed O D 0 M1.
+
+lemma critical: βˆ€O,D,ty,M,N. 
+  βˆƒM3:T O D
+  .star (T O D) (red O D) (subst O D M 0 N) M3
+   βˆ§star (T O D) (red O D)
+    (App O D
+     (Vec O D ty
+      (map (FinSet_of_FType O D ty) (T O D)
+       (Ξ»a0:FinSet_of_FType O D ty.subst O D M 0 (to_T O D ty a0))
+       (enum (FinSet_of_FType O D ty)))) N) M3.
+#O #D #ty #M #N
+lapply (canonical_to_T O D N ty) * #a #Ha
+%{(subst O D M 0 (to_T O D ty a))} (* CR-term *)
+%[@red_star_subst @Ha
+ |@trans_star [|@(star_red_appr β€¦ Ha)] @R_to_star @riota
+  lapply (enum_complete (FinSet_of_FType O D ty) a)
+  elim (enum (FinSet_of_FType O D ty))
+   [normalize #H1 destruct (H1)
+   |#hd #tl #Hind #H cases (orb_true_l β€¦ H) -H #Hcase
+     [normalize >Hcase >(\P Hcase) //
+     |normalize cases (true_or_false (a==hd)) #Hcase1
+       [normalize >Hcase1 >(\P Hcase1) // |>Hcase1 @Hind @Hcase]
+     ]
+   ]
+ ]
+qed.
+
+lemma critical2: βˆ€O,D,ty,a,M,M1,M2,v.
+  red O D (Vec O D ty v) M β†’
+  red O D (App O D (Vec O D ty v) (to_T O D ty a)) M1 β†’
+  assoc (FinSet_of_FType O D ty) (T O D) a (enum (FinSet_of_FType O D ty)) v
+    =Some (T O D) M2 β†’
+  βˆƒM3:T O D
+  .star (T O D) (red O D) M2 M3
+   βˆ§star (T O D) (red O D) (App O D M (to_T O D ty a)) M3.
+#O #D #ty #a #M #M1 #M2 #v #redM #redM1 #Ha lapply (red_vec β€¦ redM) -redM
+* #N * #N1 * #v1 * #v2 * * #Hred1 #Hv #HM0 >HM0 -HM0 >Hv in Ha; #Ha
+cases (same_assoc β€¦ a (enum (FinSet_of_FType O D ty)) v1 v2 N N1)
+  [* >Ha -Ha #H1 destruct (H1) #Ha
+   %{N1} (* CR-term *) % [@R_to_star //|@R_to_star @(riota β€¦ Ha)]
+  |#Ha1 %{M2} (* CR-term *) % [// | @R_to_star @riota <Ha1 @Ha]
+  ]
+qed.
+
+
+lemma critical3: βˆ€O,D,ty,M1,M2. red O D M1 M2 β†’ 
+  βˆƒM3:T O D.star (T O D) (red O D) (Lambda O D ty M2) M3
+   βˆ§star (T O D) (red O D)
+    (Vec O D ty
+     (map (FinSet_of_FType O D ty) (T O D)
+      (Ξ»a:FinSet_of_FType O D ty.subst O D M1 0 (to_T O D ty a))
+      (enum (FinSet_of_FType O D ty)))) M3.
+#O #D #ty #M1 #M2 #Hred
+ %{(Vec O D ty
+    (map (FinSet_of_FType O D ty) (T O D)
+    (Ξ»a:FinSet_of_FType O D ty.subst O D M2 0 (to_T O D ty a))
+    (enum (FinSet_of_FType O D ty))))} (* CR-term *) %
+  [@R_to_star @rmem
+  |@star_red_vec2 [>length_map >length_map //] #n #M0
+   cases (true_or_false (leb (|enum (FinSet_of_FType O D ty)|) n)) #Hcase
+    [>nth_to_default [2:>length_map @(leb_true_to_le β€¦ Hcase)]
+     >nth_to_default [2:>length_map @(leb_true_to_le β€¦ Hcase)] //
+    |cut (n < |enum (FinSet_of_FType O D ty)|) 
+      [@not_le_to_lt @leb_false_to_not_le @Hcase] #Hlt
+     cut (βˆƒa:FinSet_of_FType O D ty.True)
+      [lapply Hlt lapply (enum_complete (FinSet_of_FType O D ty))
+       cases (enum (FinSet_of_FType O D ty)) 
+        [#_ normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
+        |#a #l #_ #_ %{a} //
+        ]
+      ] * #a #_
+     >(nth_map ?????? a Hlt) >(nth_map ?????? a Hlt) #_
+     @red_star_subst2 // 
+    ]
+  ]
+qed.
+
+(* we need to proceed by structural induction on the term and then
+by inversion on the two redexes. The problem are the moves in a 
+same subterm, since we need an induction hypothesis, there *)
+
+lemma local_confluence: βˆ€O,D,M,M1,M2. red O D M M1 β†’ red O D M M2 β†’ 
+βˆƒM3. star ? (red O D) M1 M3 βˆ§ star ? (red O D) M2 M3. 
+#O #D #M @(T_elim β€¦ M)
+  [#o #a #M1 #M2 #H elim(red_val ????? H)
+  |#n #M1 #M2 #H elim(red_rel ???? H)
+  |(* app : this is the interesting case *)
+   #P #Q #HindP #HindQ
+   #M1 #M2 #H1 inversion H1 -H1
+    [(* right redex is beta *)
+     #ty #Q #N #Hc #HM >HM -HM #HM1 >HM1 - HM1 #Hl inversion Hl
+      [#ty1 #Q1 #N1 #Hc1 #H1 destruct (H1) #H_ 
+       %{(subst O D Q1 0 N1)} (* CR-term *) /2/
+      |#ty #v #a #M0 #_ #H1 destruct (H1) (* vacuous *)
+      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #_ cases (red_lambda β€¦ redM0)
+        [* #Q1 * #redQ #HM10 >HM10 
+         %{(subst O D Q1 0 N0)} (* CR-term *) %
+          [@red_star_subst2 //|@R_to_star @rbeta @Hc]
+        |#HM1 >HM1 @critical
+        ]
+      |#M0 #N0 #N1 #redN0N1 #_ #H1 destruct (H1) #HM2
+       %{(subst O D Q 0 N1)} (* CR-term *) 
+       %[@red_star_subst @R_to_star //|@R_to_star @rbeta @(red_closed β€¦ Hc) //]
+      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
+      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      ] 
+    |(* right redex is iota *)#ty #v #a #M3 #Ha #_ #_ #Hl inversion Hl
+      [#P1 #M1 #N1 #_ #H1 destruct (H1) (* vacuous *)
+      |#ty1 #v1 #a1 #M4 #Ha1 #H1 destruct (H1) -H1 #HM4 >(inj_to_T β€¦ e0) in Ha;
+       >Ha1 #H1 destruct (H1) %{M3} (* CR-term *) /2/
+      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #HM2 @(critical2 β€¦ redM0 Hl Ha)
+      |#M0 #N0 #N1 #redN0N1 #_ #H1 destruct (H1) elim (normal_to_T β€¦ redN0N1)
+      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
+      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      ]
+    |(* right redex is appl *)#M3 #M4 #N #redM3M4 #_ #H1 destruct (H1) #_ 
+      #Hl inversion Hl
+      [#ty1 #M1 #N1 #Hc #H1 destruct (H1) #HM2 lapply (red_lambda β€¦ redM3M4) *
+        [* #M3 * #H1 #H2 >H2 %{(subst O D M3 0 N1)} %
+          [@R_to_star @rbeta @Hc|@red_star_subst2 // ]
+        |#H >H -H lapply (critical O D ty1 M1 N1) * #M3 * #H1 #H2 
+         %{M3} /2/
+        ]
+      |#ty1 #v1 #a1 #M4 #Ha1 #H1 #H2 destruct 
+       lapply (critical2 β€¦ redM3M4 Hl Ha1) * #M3 * #H1 #H2 %{M3} /2/
+      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #HM2 
+       lapply (HindP β€¦ redM0 redM3M4) * #M3 * #H1 #H2 
+       %{(App O D M3 N0)} (* CR-term *) % [@star_red_appl //|@star_red_appl //]
+      |#M0 #N0 #N1 #redN0N1 #_ #H1 destruct (H1) #_
+       %{(App O D M4 N1)} % @R_to_star [@rappr //|@rappl //]
+      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
+      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      ]
+    |(* right redex is appr *)#M3 #N #N1 #redN #_ #H1 destruct (H1) #_ 
+      #Hl inversion Hl
+      [#ty1 #M0 #N0 #Hc #H1 destruct (H1) #HM2 
+       %{(subst O D M0 0 N1)} (* CR-term *) % 
+        [@R_to_star @rbeta @(red_closed β€¦ Hc) //|@red_star_subst @R_to_star // ]
+      |#ty1 #v1 #a1 #M4 #Ha1 #H1 #H2 destruct (H1) elim (normal_to_T β€¦ redN)
+      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #HM2 
+       %{(App O D M10 N1)} (* CR-term *) % @R_to_star [@rappl //|@rappr //]
+      |#M0 #N0 #N10 #redN0 #_ #H1 destruct (H1) #_
+       lapply (HindQ β€¦ redN0 redN) * #M3 * #H1 #H2 
+       %{(App O D M0 M3)} (* CR-term *) % [@star_red_appr //|@star_red_appr //]
+      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
+      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
+      ]
+    |(* right redex is rlam *) #ty #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
+    |(* right redex is rmem *) #ty #M0 #H1 destruct (H1) (* vacuous *)
+    |(* right redex is vec *) #ty #N #N1 #v #v1 #_ #_ 
+     #H1 destruct (H1) (* vacuous *)
+    ]
+  |#ty #M1 #Hind #M2 #M3 #H1 #H2 (* this case is not trivial any more *)
+   lapply (red_lambda β€¦ H1) *
+    [* #M4 * #H3 #H4 >H4 lapply (red_lambda β€¦ H2) *
+      [* #M5 * #H5 #H6 >H6 lapply(Hind β€¦ H3 H5) * #M6 * #H7 #H8 
+       %{(Lambda O D ty M6)} (* CR-term *) % @star_red_lambda //
+      |#H5 >H5 @critical3 // 
+      ]
+    |#HM2 >HM2 lapply (red_lambda β€¦ H2) *
+      [* #M4 * #Hred #HM3 >HM3 lapply (critical3 β€¦ ty ?? Hred) * #M5
+       * #H3 #H4 %{M5} (* CR-term *) % //
+      |#HM3 >HM3 %{M3} (* CR-term *) % // 
+      ]
+    ]
+  |#ty #v1 #Hind #M1 #M2 #H1 #H2
+   lapply (red_vec β€¦ H1) * #N11 * #N12 * #v11 * #v12 * * #redN11 #Hv1 #HM1
+   lapply (red_vec β€¦ H2) * #N21* #N22 * #v21 * #v22 * * #redN21 #Hv2 #HM2
+   >Hv1 in Hv2; #Hvv lapply (compare_append β€¦ Hvv) -Hvv * 
+   (* we must proceed by cases on the list *) * normalize
+    [(* N11 = N21 *) *
+      [>append_nil * #Hl1 #Hl2 destruct lapply(Hind N11 β€¦ redN11 redN21)
+        [@mem_append_l2 %1 //]
+       * #M3 * #HM31 #HM32
+       %{(Vec O D ty (v21@M3::v12))} (* CR-term *) 
+       % [@star_red_vec //|@star_red_vec //]
+      |>append_nil * #Hl1 #Hl2 destruct lapply(Hind N21 β€¦ redN21 redN11)
+        [@mem_append_l2 %1 //]
+       * #M3 * #HM31 #HM32
+       %{(Vec O D ty (v11@M3::v22))} (* CR-term *) 
+       % [@star_red_vec //|@star_red_vec //]
+      ]
+    |(* N11 β‰   N21 *) -Hind #P #l *
+      [* #Hv11 #Hv22 destruct
+       %{((Vec O D ty ((v21@N22::l)@N12::v12)))} (* CR-term *) % @R_to_star 
+        [>associative_append >associative_append normalize @rvec //
+        |>append_cons <associative_append <append_cons in βŠ’ (???%?); @rvec //
+        ]
+      |* #Hv11 #Hv22 destruct
+       %{((Vec O D ty ((v11@N12::l)@N22::v22)))} (* CR-term *) % @R_to_star 
+        [>append_cons <associative_append <append_cons in βŠ’ (???%?); @rvec //
+        |>associative_append >associative_append normalize @rvec //
+        ]
+      ]
+    ]
+  ]
+qed.    
+      
+
+
+
diff --git a/matita/matita/broken_lib/finite_lambda/reduction.ma b/matita/matita/broken_lib/finite_lambda/reduction.ma
new file mode 100644 (file)
index 0000000..98c56e1
--- /dev/null
@@ -0,0 +1,308 @@
+(*
+    ||M||  This file is part of HELM, an Hypertextual, Electronic        
+    ||A||  Library of Mathematics, developed at the Computer Science     
+    ||T||  Department of the University of Bologna, Italy.                     
+    ||I||                                                                 
+    ||T||  
+    ||A||  This file is distributed under the terms of the 
+    \   /  GNU General Public License Version 2        
+     \ /      
+      V_______________________________________________________________ *)
+
+include "finite_lambda/terms_and_types.ma".
+
+(* some auxiliary lemmas *)
+
+lemma nth_to_default: βˆ€A,l,n,d. 
+  |l| β‰€ n β†’ nth n A l d = d.
+#A #l elim l [//] #a #tl #Hind #n cases n
+  [#d normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
+  |#m #d normalize #H @Hind @le_S_S_to_le @H
+  ]
+qed.
+
+lemma mem_nth: βˆ€A,l,n,d. 
+  n < |l|  β†’ mem ? (nth n A l d) l.
+#A #l elim l   
+  [#n #d normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
+  |#a #tl #Hind * normalize 
+    [#_ #_ %1 //| #m #d #HSS %2 @Hind @le_S_S_to_le @HSS]
+  ]
+qed.
+
+lemma nth_map: βˆ€A,B,l,f,n,d1,d2. 
+  n < |l| β†’ nth n B (map β€¦ f l) d1 = f (nth n A l d2).
+#n #B #l #f elim l 
+  [#m #d1 #d2 normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
+  |#a #tl #Hind #m #d1 #d2 cases m normalize // 
+   #m1 #H @Hind @le_S_S_to_le @H
+  ]
+qed.
+
+
+
+(* end of auxiliary lemmas *)
+
+let rec to_T O D ty on ty: FinSet_of_FType O D ty β†’ T O D β‰ 
+  match ty return (Ξ»ty.FinSet_of_FType O D ty β†’ T O D) with 
+  [atom o β‡’ Ξ»a.Val O D o a
+  |arrow ty1 ty2 β‡’ Ξ»a:FinFun ??.Vec O D ty1  
+    (map ((FinSet_of_FType O D ty1)Γ—(FinSet_of_FType O D ty2)) 
+     (T O D) (Ξ»p.to_T O D ty2 (snd β€¦ p)) (pi1 β€¦ a))
+  ]
+.
+
+lemma is_closed_to_T: βˆ€O,D,ty,a. is_closed O D 0 (to_T O D ty a).
+#O #D #ty elim ty //
+#ty1 #ty2 #Hind1 #Hind2 #a normalize @cvec #m #Hmem
+lapply (mem_map ????? Hmem) * #a1 * #H1 #H2 <H2 @Hind2 
+qed.
+
+axiom inj_to_T: βˆ€O,D,ty,a1,a2. to_T O D ty a1 = to_T O D ty a2 β†’ a1 = a2. 
+(* complicata 
+#O #D #ty elim ty 
+  [#o normalize #a1 #a2 #H destruct //
+  |#ty1 #ty2 #Hind1 #Hind2 * #l1 #Hl1 * #l2 #Hl2 normalize #H destruct -H
+   cut (l1=l2) [2: #H generalize in match Hl1; >H //] -Hl1 -Hl2
+   lapply e0 -e0 lapply l2 -l2 elim l1 
+    [#l2 cases l2 normalize [// |#a1 #tl1 #H destruct]
+    |#a1 #tl1 #Hind #l2 cases l2 
+      [normalize #H destruct
+      |#a2 #tl2 normalize #H @eq_f2
+        [@Hind2 *)
+        
+let rec assoc (A:FinSet) (B:Type[0]) (a:A) l1 l2 on l1 : option B β‰
+  match l1 with
+  [ nil β‡’  None ?
+  | cons hd1 tl1 β‡’ match l2 with
+    [ nil β‡’ None ?
+    | cons hd2 tl2 β‡’ if a==hd1 then Some ? hd2 else assoc A B a tl1 tl2
+    ]
+  ]. 
+  
+lemma same_assoc: βˆ€A,B,a,l1,v1,v2,N,N1.
+  assoc A B a l1 (v1@N::v2) = Some ? N βˆ§ assoc A B a l1 (v1@N1::v2) = Some ? N1 
+   βˆ¨ assoc A B a l1 (v1@N::v2) = assoc A B a l1 (v1@N1::v2).
+#A #B #a #l1 #v1 #v2 #N #N1 lapply v1 -v1 elim l1 
+  [#v1 %2 // |#hd #tl #Hind * normalize cases (a==hd) normalize /3/]
+qed.
+
+lemma assoc_to_mem: βˆ€A,B,a,l1,l2,b. 
+  assoc A B a l1 l2 = Some ? b β†’ mem ? b l2.
+#A #B #a #l1 elim l1
+  [#l2 #b normalize #H destruct
+  |#hd1 #tl1 #Hind * 
+    [#b normalize #H destruct
+    |#hd2 #tl2 #b normalize cases (a==hd1) normalize
+      [#H %1 destruct //|#H %2 @Hind @H]
+    ]
+  ]
+qed.
+
+lemma assoc_to_mem2: βˆ€A,B,a,l1,l2,b. 
+  assoc A B a l1 l2 = Some ? b β†’ βˆƒl21,l22.l2=l21@b::l22.
+#A #B #a #l1 elim l1
+  [#l2 #b normalize #H destruct
+  |#hd1 #tl1 #Hind * 
+    [#b normalize #H destruct
+    |#hd2 #tl2 #b normalize cases (a==hd1) normalize
+      [#H %{[]} %{tl2} destruct //
+      |#H lapply (Hind β€¦ H) * #la * #lb #H1 
+       %{(hd2::la)} %{lb} >H1 //]
+    ]
+  ]
+qed.
+
+lemma assoc_map: βˆ€A,B,C,a,l1,l2,f,b. 
+  assoc A B a l1 l2 = Some ? b β†’ assoc A C a l1 (map ?? f l2) = Some ? (f b).
+#A #B #C #a #l1 elim l1
+  [#l2 #f #b normalize #H destruct
+  |#hd1 #tl1 #Hind * 
+    [#f #b normalize #H destruct
+    |#hd2 #tl2 #f #b normalize cases (a==hd1) normalize
+      [#H destruct // |#H @(Hind β€¦ H)]
+    ]
+  ]
+qed.
+
+(*************************** One step reduction *******************************)
+
+inductive red (O:Type[0]) (D:Oβ†’FinSet) : T O D  β†’T O D β†’ Prop β‰
+  | (* we only allow beta on closed arguments *)
+    rbeta: βˆ€P,M,N. is_closed O D 0 N β†’
+      red O D (App O D (Lambda O D P M) N) (subst O D M 0 N)
+  | riota: βˆ€ty,v,a,M. 
+      assoc ?? a (enum (FinSet_of_FType O D ty)) v = Some ? M β†’
+      red O D (App O D (Vec O D ty v) (to_T O D ty a)) M
+  | rappl: βˆ€M,M1,N. red O D M M1 β†’ red O D (App O D M N) (App O D M1 N)
+  | rappr: βˆ€M,N,N1. red O D N N1 β†’ red O D (App O D M N) (App O D M N1)
+  | rlam: βˆ€ty,N,N1. red O D N N1 β†’ red O D (Lambda O D ty N) (Lambda O D ty N1) 
+  | rmem: βˆ€ty,M. red O D (Lambda O D ty M)
+      (Vec O D ty (map ?? (Ξ»a. subst O D M 0 (to_T O D ty a)) 
+      (enum (FinSet_of_FType O D ty)))) 
+  | rvec: βˆ€ty,N,N1,v,v1. red O D N N1 β†’ 
+      red O D (Vec O D ty (v@N::v1)) (Vec O D ty (v@N1::v1)).
+(*********************************** inversion ********************************)
+lemma red_vec: βˆ€O,D,ty,v,M.
+  red O D (Vec O D ty v) M β†’ βˆƒN,N1,v1,v2.
+      red O D N N1 βˆ§ v = v1@N::v2 βˆ§ M = Vec O D ty (v1@N1::v2).
+#O #D #ty #v #M #Hred inversion Hred
+  [#ty1 #M0 #N #Hc #H destruct
+  |#ty1 #v1 #a #M0 #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#ty1 #M #M1 #_ #_ #H destruct
+  |#ty1 #M0 #H destruct
+  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct #_ %{N} %{N1} %{v1} %{v2} /3/
+  ]
+qed.
+      
+lemma red_lambda: βˆ€O,D,ty,M,N.
+  red O D (Lambda O D ty M) N β†’ 
+      (βˆƒM1. red O D M M1 βˆ§ N = (Lambda O D ty M1)) βˆ¨
+      N = Vec O D ty (map ?? (Ξ»a. subst O D M 0 (to_T O D ty a)) 
+      (enum (FinSet_of_FType O D ty))).
+#O #D #ty #M #N #Hred inversion Hred
+  [#ty1 #M0 #N #Hc #H destruct
+  |#ty1 #v1 #a #M0 #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#ty1 #P #P1 #redP #_ #H #H1 destruct %1 %{P1} % //
+  |#ty1 #M0 #H destruct #_ %2 //
+  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct
+  ]
+qed. 
+
+lemma red_val: βˆ€O,D,ty,a,N.
+  red O D (Val O D ty a) N β†’ False.
+#O #D #ty #M #N #Hred inversion Hred
+  [#ty1 #M0 #N #Hc #H destruct
+  |#ty1 #v1 #a #M0 #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#ty1 #N1 #N2 #_ #_ #H destruct
+  |#ty1 #M0 #H destruct #_ 
+  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct
+  ]
+qed. 
+
+lemma red_rel: βˆ€O,D,n,N.
+  red O D (Rel O D n) N β†’ False.
+#O #D #n #N #Hred inversion Hred
+  [#ty1 #M0 #N #Hc #H destruct
+  |#ty1 #v1 #a #M0 #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#M0 #M1 #N #_ #_ #H destruct
+  |#ty1 #N1 #N2 #_ #_ #H destruct
+  |#ty1 #M0 #H destruct #_ 
+  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct
+  ]
+qed. 
+(*************************** multi step reduction *****************************)
+lemma star_red_appl: βˆ€O,D,M,M1,N. star ? (red O D) M M1 β†’ 
+  star ? (red O D) (App O D M N) (App O D M1 N).
+#O #D #M #N #N1 #H elim H // 
+#P #Q #Hind #HPQ #Happ %1[|@Happ] @rappl @HPQ
+qed.
+
+lemma star_red_appr: βˆ€O,D,M,N,N1. star ? (red O D) N N1 β†’ 
+  star ? (red O D) (App O D M N) (App O D M N1).
+#O #D #M #N #N1 #H elim H // 
+#P #Q #Hind #HPQ #Happ %1[|@Happ] @rappr @HPQ
+qed.
+
+lemma star_red_vec: βˆ€O,D,ty,N,N1,v1,v2. star ? (red O D) N N1 β†’ 
+  star ? (red O D) (Vec O D ty (v1@N::v2)) (Vec O D ty (v1@N1::v2)).
+#O #D #ty #N #N1 #v1 #v2 #H elim H // 
+#P #Q #Hind #HPQ #Hvec %1[|@Hvec] @rvec @HPQ
+qed.
+
+lemma star_red_vec1: βˆ€O,D,ty,v1,v2,v. |v1| = |v2| β†’
+  (βˆ€n,M. n < |v1| β†’ star ? (red O D) (nth n ? v1 M) (nth n ? v2 M)) β†’ 
+  star ? (red O D) (Vec O D ty (v@v1)) (Vec O D ty (v@v2)).
+#O #D #ty #v1 elim v1 
+  [#v2 #v normalize #Hv2 >(lenght_to_nil β€¦ (sym_eq β€¦ Hv2)) normalize //
+  |#N1 #tl1 #Hind * [normalize #v #H destruct] #N2 #tl2 #v normalize #HS
+   #H @(trans_star β€¦ (Vec O D ty (v@N2::tl1)))
+    [@star_red_vec @(H 0 N1) @le_S_S //
+    |>append_cons >(append_cons ??? tl2) @(Hind… (injective_S β€¦ HS))
+     #n #M #H1 @(H (S n)) @le_S_S @H1
+    ]
+  ]
+qed.
+
+lemma star_red_vec2: βˆ€O,D,ty,v1,v2. |v1| = |v2| β†’
+  (βˆ€n,M. n < |v1| β†’ star ? (red O D) (nth n ? v1 M) (nth n ? v2 M)) β†’ 
+  star ? (red O D) (Vec O D ty v1) (Vec O D ty v2).
+#O #D #ty #v1 #v2 @(star_red_vec1 β€¦ [ ])
+qed.
+
+lemma star_red_lambda: βˆ€O,D,ty,N,N1. star ? (red O D) N N1 β†’ 
+  star ? (red O D) (Lambda O D ty N) (Lambda O D ty N1).
+#O #D #ty #N #N1 #H elim H // 
+#P #Q #Hind #HPQ #Hlam %1[|@Hlam] @rlam @HPQ
+qed.
+
+(************************ reduction and substitution **************************)
+  
+lemma red_star_subst : βˆ€O,D,M,N,N1,i. 
+  star ? (red O D) N N1 β†’ star ? (red O D) (subst O D M i N) (subst O D M i N1).
+#O #D #M #N #N1 #i #Hred lapply i -i @(T_elim β€¦ M) normalize
+  [#o #a #i //
+  |#i #n cases (leb n i) normalize // cases (eqb n i) normalize //
+  |#P #Q #HindP #HindQ #n normalize 
+   @(trans_star β€¦ (App O D (subst O D P n N1) (subst O D Q n N))) 
+    [@star_red_appl @HindP |@star_red_appr @HindQ]
+  |#ty #P #HindP #i @star_red_lambda @HindP
+  |#ty #v #Hindv #i @star_red_vec2 [>length_map >length_map //]
+   #j #Q inversion v [#_ normalize //] #a #tl #_ #Hv
+   cases (true_or_false (leb (S j) (|a::tl|))) #Hcase
+    [lapply (leb_true_to_le β€¦ Hcase) -Hcase #Hcase
+     >(nth_map ?????? a Hcase) >(nth_map ?????? a Hcase) #_ @Hindv >Hv @mem_nth //
+    |>nth_to_default 
+      [2:>length_map @le_S_S_to_le @not_le_to_lt @leb_false_to_not_le //]
+     >nth_to_default 
+      [2:>length_map @le_S_S_to_le @not_le_to_lt @leb_false_to_not_le //] //
+    ]
+  ]
+qed.
+     
+lemma red_star_subst2 : βˆ€O,D,M,M1,N,i. is_closed O D 0 N β†’ 
+  red O D M M1 β†’ star ? (red O D) (subst O D M i N) (subst O D M1 i N).
+#O #D #M #M1 #N #i #HNc #Hred lapply i -i elim Hred
+  [#ty #P #Q #HQc #i normalize @starl_to_star @sstepl 
+   [|@rbeta >(subst_closed β€¦ HQc) //] >(subst_closed β€¦ HQc) // 
+    lapply (subst_lemma ?? P ?? i 0 (is_closed_mono β€¦ HQc) HNc) // 
+    <plus_n_Sm <plus_n_O #H <H //
+  |#ty #v #a #P #HP #i normalize >(subst_closed β€¦ (le_O_n β€¦)) //
+   @R_to_star @riota @assoc_map @HP 
+  |#P #P1 #Q #Hred #Hind #i normalize @star_red_appl @Hind
+  |#P #P1 #Q #Hred #Hind #i normalize @star_red_appr @Hind
+  |#ty #P #P1 #Hred #Hind #i normalize @star_red_lambda @Hind
+  |#ty #P #i normalize @starl_to_star @sstepl [|@rmem] 
+   @star_to_starl @star_red_vec2 [>length_map >length_map >length_map //]
+   #n #Q >length_map #H
+   cut (βˆƒa:(FinSet_of_FType O D ty).True) 
+    [lapply H -H lapply (enum_complete (FinSet_of_FType O D ty))
+     cases (enum (FinSet_of_FType O D ty)) 
+      [#x normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
+      |#x #l #_ #_ %{x} //
+      ]
+    ] * #a #_
+   >(nth_map ?????? a H) >(nth_map ?????? Q) [2:>length_map @H] 
+   >(nth_map ?????? a H) 
+   lapply (subst_lemma O D P (to_T O D ty
+    (nth n (FinSet_of_FType O D ty) (enum (FinSet_of_FType O D ty)) a)) 
+   N i 0 (is_closed_mono β€¦ (is_closed_to_T β€¦)) HNc) // <plus_n_O #H1 >H1
+   <plus_n_Sm <plus_n_O //
+  |#ty #P #Q #v #v1 #Hred #Hind #n normalize 
+   <map_append <map_append @star_red_vec @Hind
+  ]
+qed.
+   
+
+
+
+
diff --git a/matita/matita/broken_lib/finite_lambda/terms_and_types.ma b/matita/matita/broken_lib/finite_lambda/terms_and_types.ma
new file mode 100644 (file)
index 0000000..1ae47c2
--- /dev/null
@@ -0,0 +1,326 @@
+(*
+    ||M||  This file is part of HELM, an Hypertextual, Electronic        
+    ||A||  Library of Mathematics, developed at the Computer Science     
+    ||T||  Department of the University of Bologna, Italy.                     
+    ||I||                                                                 
+    ||T||  
+    ||A||  This file is distributed under the terms of the 
+    \   /  GNU General Public License Version 2        
+     \ /      
+      V_______________________________________________________________ *)
+
+include "basics/finset.ma".
+include "basics/star.ma".
+
+
+inductive FType (O:Type[0]): Type[0] β‰
+  | atom : O β†’ FType O 
+  | arrow : FType O β†’ FType O β†’ FType O. 
+
+inductive T (O:Type[0]) (D:O β†’ FinSet): Type[0] β‰
+  | Val: βˆ€o:O.carr (D o) β†’ T O D        (* a value in a finset *)
+  | Rel: nat β†’ T O D                    (* DB index, base is 0 *)
+  | App: T O D β†’ T O D β†’ T O D          (* function, argument *)
+  | Lambda: FType O β†’ T O D β†’ T O D     (* type, body *)
+  | Vec: FType O β†’ list (T O D) β†’ T O D (* type, body *)
+.
+
+let rec FinSet_of_FType O (D:Oβ†’FinSet) (ty:FType O) on ty : FinSet β‰
+  match ty with
+  [atom o β‡’ D o
+  |arrow ty1 ty2 β‡’ FinFun (FinSet_of_FType O D ty1) (FinSet_of_FType O D ty2)
+  ].
+
+(* size *)
+
+let rec size O D (M:T O D) on M β‰
+match M with
+  [Val o a β‡’ 1
+  |Rel n β‡’ 1
+  |App P Q β‡’ size O D P + size O D Q + 1
+  |Lambda Ty P β‡’ size O D P + 1
+  |Vec Ty v β‡’ foldr ?? (Ξ»x,a. size O D x + a) 0 v +1
+  ]
+.
+
+(* axiom pos_size: βˆ€M. 1 β‰€ size M. *)
+
+theorem Telim_size: βˆ€O,D.βˆ€P: T O D β†’ Prop. 
+ (βˆ€M. (βˆ€N. size O D N < size O D M β†’ P N) β†’ P M) β†’ βˆ€M. P M.
+#O #D #P #H #M (cut (βˆ€p,N. size O D N = p β†’ P N))
+  [2: /2/]
+#p @(nat_elim1 p) #m #H1 #N #sizeN @H #N0 #Hlt @(H1 (size O D N0)) //
+qed.
+
+lemma T_elim: 
+  βˆ€O: Type[0].βˆ€D:Oβ†’FinSet.βˆ€P:T O Dβ†’Prop.
+  (βˆ€o:O.βˆ€x:D o.P (Val O D o x)) β†’
+  (βˆ€n:β„•.P(Rel O D n)) β†’
+  (βˆ€m,n:T O D.P mβ†’P nβ†’P (App O D m n)) β†’
+  (βˆ€Ty:FType O.βˆ€m:T O D.P mβ†’P(Lambda O D Ty m)) β†’
+  (βˆ€Ty:FType O.βˆ€v:list (T O D).
+     (βˆ€x:T O D. mem ? x v β†’ P x) β†’ P(Vec O D Ty v)) β†’
+  βˆ€x:T O D.P x.
+#O #D #P #Hval #Hrel #Happ #Hlam #Hvec @Telim_size #x cases x //
+  [ (* app *) #m #n #Hind @Happ @Hind // /2 by le_minus_to_plus/
+  | (* lam *) #ty #m #Hind @Hlam @Hind normalize // 
+  | (* vec *) #ty #v #Hind @Hvec #x lapply Hind elim v
+    [#Hind normalize *
+    |#hd #tl #Hind1 #Hind2 * 
+      [#Hx >Hx @Hind2 normalize //
+      |@Hind1 #N #H @Hind2 @(lt_to_le_to_lt β€¦ H) normalize //
+      ]
+    ]
+  ]
+qed.
+
+(* since we only consider beta reduction with closed arguments we could avoid
+lifting. We define it for the sake of generality *)
+        
+(* arguments: k is the nesting depth (starts from 0), p is the lift 
+let rec lift O D t k p on t β‰ 
+  match t with 
+    [ Val o a β‡’ Val O D o a
+    | Rel n β‡’ if (leb k n) then Rel O D (n+p) else Rel O D n
+    | App m n β‡’ App O D (lift O D m k p) (lift O D n k p)
+    | Lambda Ty n β‡’ Lambda O D Ty (lift O D n (S k) p)
+    | Vec Ty v β‡’ Vec O D Ty (map ?? (Ξ»x. lift O D x k p) v) 
+    ].
+
+notation "↑ ^ n ( M )" non associative with precedence 40 for @{'Lift 0 $n $M}.
+notation "↑ _ k ^ n ( M )" non associative with precedence 40 for @{'Lift $n $k $M}.
+
+interpretation "Lift" 'Lift n k M = (lift ?? M k n). 
+
+let rec subst O D t k s on t β‰ 
+  match t with 
+    [ Val o a β‡’ Val O D o a 
+    | Rel n β‡’ if (leb k n) then
+        (if (eqb k n) then lift O D s 0 n else Rel O D (n-1)) 
+        else(Rel O D n)
+    | App m n β‡’ App O D (subst O D m k s) (subst O D n k s)
+    | Lambda T n β‡’ Lambda O D T (subst O D n (S k) s)
+    | Vec T v β‡’ Vec O D T (map ?? (Ξ»x. subst O D x k s) v) 
+    ].
+*)
+
+(* simplified version of subst, assuming the argument s is closed *)
+
+let rec subst O D t k s on t β‰ 
+  match t with 
+    [ Val o a β‡’ Val O D o a 
+    | Rel n β‡’ if (leb k n) then
+        (if (eqb k n) then (* lift O D s 0 n*) s else Rel O D (n-1)) 
+        else(Rel O D n)
+    | App m n β‡’ App O D (subst O D m k s) (subst O D n k s)
+    | Lambda T n β‡’ Lambda O D T (subst O D n (S k) s)
+    | Vec T v β‡’ Vec O D T (map ?? (Ξ»x. subst O D x k s) v) 
+    ].
+(* notation "hvbox(M break [ k β‰ N ])" 
+   non associative with precedence 90
+   for @{'Subst1 $M $k $N}. *)
+interpretation "Subst" 'Subst1 M k N = (subst M k N). 
+
+(*
+lemma subst_rel1: βˆ€O,D,A.βˆ€k,i. i < k β†’ 
+  (Rel O D i) [k β‰ A] = Rel O D i.
+#A #k #i normalize #ltik >(lt_to_leb_false β€¦ ltik) //
+qed.
+
+lemma subst_rel2: βˆ€O,D, A.βˆ€k. 
+  (Rel k) [k β‰ A] = lift A 0 k.
+#A #k normalize >(le_to_leb_true k k) // >(eq_to_eqb_true β€¦ (refl β€¦)) //
+qed.
+
+lemma subst_rel3: βˆ€A.βˆ€k,i. k < i β†’ 
+  (Rel i) [k β‰ A] = Rel (i-1).
+#A #k #i normalize #ltik >(le_to_leb_true k i) /2/ 
+>(not_eq_to_eqb_false k i) // @lt_to_not_eq //
+qed. *)
+
+
+(* closed terms ????
+let rec closed_k O D (t: T O D) k on t β‰ 
+  match t with 
+    [ Val o a β‡’ True
+    | Rel n β‡’ n < k 
+    | App m n β‡’ (closed_k O D m k) βˆ§ (closed_k O D n k)
+    | Lambda T n β‡’ closed_k O D n (k+1)
+    | Vec T v β‡’ closed_list O D v k
+    ]
+    
+and closed_list O D (l: list (T O D)) k on l β‰
+  match l with
+    [ nil β‡’ True
+    | cons hd tl β‡’ closed_k O D hd k βˆ§ closed_list O D tl k
+    ]
+. *)
+
+inductive is_closed (O:Type[0]) (D:Oβ†’FinSet): nat β†’ T O D β†’ Prop β‰
+| cval : βˆ€k,o,a.is_closed O D k (Val O D o a)
+| crel : βˆ€k,n. n < k β†’ is_closed O D k (Rel O D n)
+| capp : βˆ€k,m,n. is_closed O D k m β†’ is_closed O D k n β†’ 
+           is_closed O D k (App O D m n)
+| clam : βˆ€T,k,m. is_closed O D (S k) m β†’ is_closed O D k (Lambda O D T m)
+| cvec:  βˆ€T,k,v. (βˆ€m. mem ? m v β†’ is_closed O D k m) β†’ 
+           is_closed O D k (Vec O D T v).
+      
+lemma is_closed_rel: βˆ€O,D,n,k.
+  is_closed O D k (Rel O D n) β†’ n < k.
+#O #D #n #k #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct //
+  |#k0 #M #N #_ #_ #_ #_ #_ #H destruct
+  |#T #k0 #M #_ #_ #_ #H destruct
+  |#T #k0 #v #_ #_ #_ #H destruct
+  ]
+qed.
+  
+lemma is_closed_app: βˆ€O,D,k,M, N.
+  is_closed O D k (App O D M N) β†’ is_closed O D k M βˆ§ is_closed O D k N.
+#O #D #k #M #N #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct 
+  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct % //
+  |#T #k0 #M #_ #_ #_ #H destruct
+  |#T #k0 #v #_ #_ #_ #H destruct
+  ]
+qed.
+  
+lemma is_closed_lam: βˆ€O,D,k,ty,M.
+  is_closed O D k (Lambda O D ty M) β†’ is_closed O D (S k) M.
+#O #D #k #ty #M #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct 
+  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct 
+  |#T #k0 #M1 #HM1 #_ #_ #H1 destruct //
+  |#T #k0 #v #_ #_ #_ #H destruct
+  ]
+qed.
+
+lemma is_closed_vec: βˆ€O,D,k,ty,v.
+  is_closed O D k (Vec O D ty v) β†’ βˆ€m. mem ? m v β†’ is_closed O D k m.
+#O #D #k #ty #M #H inversion H 
+  [#k0 #o #a #eqk #H destruct
+  |#k0 #n0 #ltn0 #eqk #H destruct 
+  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct 
+  |#T #k0 #M1 #HM1 #_ #_ #H1 destruct
+  |#T #k0 #v #Hv #_ #_ #H1 destruct @Hv
+  ]
+qed.
+
+lemma is_closed_S: βˆ€O,D,M,m.
+  is_closed O D m M β†’ is_closed O D (S m) M.
+#O #D #M #m #H elim H //
+  [#k #n0 #Hlt @crel @le_S //
+  |#k #P #Q #HP #HC #H1 #H2 @capp //
+  |#ty #k #P #HP #H1 @clam //
+  |#ty #k #v #Hind #Hv @cvec @Hv
+  ]
+qed.
+
+lemma is_closed_mono: βˆ€O,D,M,m,n. m β‰€ n β†’
+  is_closed O D m M β†’ is_closed O D n M.
+#O #D #M #m #n #lemn elim lemn // #i #j #H #H1 @is_closed_S @H @H1
+qed.
+  
+  
+(*** properties of lift and subst ***)
+
+(*
+lemma lift_0: βˆ€O,D.βˆ€t:T O D.βˆ€k. lift O D t k 0 = t.
+#O #D #t @(T_elim β€¦ t) normalize // 
+  [#n #k cases (leb k n) normalize // 
+  |#o #v #Hind #k @eq_f lapply Hind -Hind elim v // 
+   #hd #tl #Hind #Hind1 normalize @eq_f2 
+    [@Hind1 %1 //|@Hind #x #Hx @Hind1 %2 //]
+  ]
+qed.
+
+lemma lift_closed: βˆ€O,D.βˆ€t:T O D.βˆ€k,p. 
+  is_closed O D k t β†’ lift O D t k p = t.
+#O #D #t @(T_elim β€¦ t) normalize // 
+  [#n #k #p #H >(not_le_to_leb_false β€¦ (lt_to_not_le β€¦ (is_closed_rel β€¦ H))) //
+  |#M #N #HindM #HindN #k #p #H lapply (is_closed_app β€¦ H) * #HcM #HcN
+   >(HindM β€¦ HcM) >(HindN β€¦ HcN) //
+  |#ty #M #HindM #k #p #H lapply (is_closed_lam β€¦ H) -H #H >(HindM β€¦ H) //
+  |#ty #v #HindM #k #p #H lapply (is_closed_vec β€¦ H) -H #H @eq_f 
+   cut (βˆ€m. mem ? m v β†’ lift O D m k p = m)
+    [#m #Hmem @HindM [@Hmem | @H @Hmem]] -HindM
+   elim v // #a #tl #Hind #H1 normalize @eq_f2
+    [@H1 %1 //|@Hind #m #Hmem @H1 %2 @Hmem]
+  ]
+qed.  
+
+*)
+
+lemma subst_closed: βˆ€O,D,M,N,k,i. k β‰€ i β†’ 
+  is_closed O D k M β†’ subst O D M i N = M.
+#O #D #M @(T_elim β€¦ M)
+  [#o #a normalize //
+  |#n #N #k #j #Hlt #Hc lapply (is_closed_rel β€¦ Hc) #Hnk normalize 
+   >not_le_to_leb_false [2:@lt_to_not_le @(lt_to_le_to_lt β€¦ Hnk Hlt)] //
+  |#P #Q #HindP #HindQ #N #k #i #ltki #Hc lapply (is_closed_app β€¦ Hc) * 
+   #HcP #HcQ normalize >(HindP β€¦ ltki HcP) >(HindQ β€¦ ltki HcQ) //
+  |#ty #P #HindP #N #k #i #ltki #Hc lapply (is_closed_lam β€¦ Hc)  
+   #HcP normalize >(HindP β€¦ HcP) // @le_S_S @ltki
+  |#ty #v #Hindv #N #k #i #ltki #Hc lapply (is_closed_vec β€¦ Hc)  
+   #Hcv normalize @eq_f 
+   cut (βˆ€m:T O D.mem (T O D) m vβ†’ subst O D m i N=m)
+    [#m #Hmem @(Hindv β€¦ Hmem N β€¦ ltki) @Hcv @Hmem] 
+   elim v // #a #tl #Hind #H normalize @eq_f2
+    [@H %1 //| @Hind #Hmem #Htl @H %2 @Htl]
+  ]
+qed.
+
+lemma subst_lemma:  βˆ€O,D,A,B,C,k,i. is_closed O D k B β†’ is_closed O D i C β†’
+  subst O D (subst O D A i B) (k+i) C =
+  subst O D (subst O D A (k+S i) C) i B.
+#O #D #A #B #C #k @(T_elim β€¦ A) normalize 
+  [//
+  |#n #i #HBc #HCc @(leb_elim i n) #Hle 
+    [@(eqb_elim i n) #eqni
+      [<eqni >(lt_to_leb_false (k+(S i)) i) // normalize 
+       >(subst_closed β€¦ HBc) // >le_to_leb_true // >eq_to_eqb_true // 
+      |(cut (i < n)) 
+        [cases (le_to_or_lt_eq β€¦ Hle) // #eqin @False_ind /2/] #ltin 
+       (cut (0 < n)) [@(le_to_lt_to_lt β€¦ ltin) //] #posn
+       normalize @(leb_elim (k+i) (n-1)) #nk
+        [@(eqb_elim (k+i) (n-1)) #H normalize
+          [cut (k+(S i) = n); [/2 by S_pred/] #H1
+           >(le_to_leb_true (k+(S i)) n) /2/
+           >(eq_to_eqb_true β€¦ H1) normalize >(subst_closed β€¦ HCc) //
+          |(cut (k+i < n-1)) [@not_eq_to_le_to_lt; //] #Hlt 
+           >(le_to_leb_true (k+(S i)) n) normalize
+            [>(not_eq_to_eqb_false (k+(S i)) n) normalize
+              [>le_to_leb_true [2:@lt_to_le @(le_to_lt_to_lt β€¦ Hlt) //]
+               >not_eq_to_eqb_false // @lt_to_not_eq @(le_to_lt_to_lt β€¦ Hlt) //
+              |@(not_to_not β€¦ H) #Hn /2 by plus_minus/ 
+              ]  
+            |<plus_n_Sm @(lt_to_le_to_lt β€¦ Hlt) //
+            ]
+          ]
+        |>(not_le_to_leb_false (k+(S i)) n) normalize
+          [>(le_to_leb_true β€¦ Hle) >(not_eq_to_eqb_false β€¦ eqni) // 
+          |@(not_to_not β€¦ nk) #H @le_plus_to_minus_r //
+          ]
+        ] 
+      ]
+    |(cut (n < k+i)) [@(lt_to_le_to_lt ? i) /2 by not_le_to_lt/] #ltn 
+     >not_le_to_leb_false [2: @lt_to_not_le @(transitive_lt β€¦ltn) //] normalize 
+     >not_le_to_leb_false [2: @lt_to_not_le //] normalize
+     >(not_le_to_leb_false β€¦ Hle) // 
+    ] 
+  |#M #N #HindM #HindN #i #HBC #HCc @eq_f2 [@HindM // |@HindN //]
+  |#ty #M #HindM #i #HBC #HCc @eq_f >plus_n_Sm >plus_n_Sm @HindM // 
+   @is_closed_S //
+  |#ty #v #Hindv #i #HBC #HCc @eq_f 
+   cut (βˆ€m.mem ? m v β†’ subst O D (subst O D m i B) (k+i) C = 
+          subst O D (subst O D m (k+S i) C) i B)
+    [#m #Hmem @Hindv //] -Hindv elim v normalize [//]
+   #a #tl #Hind #H @eq_f2 [@H %1 // | @Hind #m #Hmem @H %2 //]
+  ]
+qed.
+
+
diff --git a/matita/matita/broken_lib/finite_lambda/typing.ma b/matita/matita/broken_lib/finite_lambda/typing.ma
new file mode 100644 (file)
index 0000000..791e27d
--- /dev/null
@@ -0,0 +1,229 @@
+(*
+    ||M||  This file is part of HELM, an Hypertextual, Electronic        
+    ||A||  Library of Mathematics, developed at the Computer Science     
+    ||T||  Department of the University of Bologna, Italy.                     
+    ||I||                                                                 
+    ||T||  
+    ||A||  This file is distributed under the terms of the 
+    \   /  GNU General Public License Version 2        
+     \ /      
+      V_______________________________________________________________ *)
+
+include "finite_lambda/reduction.ma".
+
+
+(****************************************************************)
+
+inductive TJ (O: Type[0]) (D:O β†’ FinSet): list (FType O) β†’ T O D β†’ FType O β†’ Prop β‰
+  | tval: βˆ€G,o,a. TJ O D G (Val O D o a) (atom O o)
+  | trel: βˆ€G1,ty,G2,n. length ? G1 = n β†’ TJ O D (G1@ty::G2) (Rel O D n) ty
+  | tapp: βˆ€G,M,N,ty1,ty2. TJ O D G M (arrow O ty1 ty2) β†’ TJ O D G N ty1 β†’
+      TJ O D G (App O D M N) ty2
+  | tlambda: βˆ€G,M,ty1,ty2. TJ O D (ty1::G) M ty2 β†’ 
+      TJ O D G (Lambda O D ty1 M) (arrow O ty1 ty2)
+  | tvec: βˆ€G,v,ty1,ty2.
+      (|v| = |enum (FinSet_of_FType O D ty1)|) β†’
+      (βˆ€M. mem ? M v β†’ TJ O D G M ty2) β†’
+      TJ O D G (Vec O D ty1 v) (arrow O ty1 ty2).
+
+lemma wt_to_T: βˆ€O,D,G,ty,a.TJ O D G (to_T O D ty a) ty.
+#O #D #G #ty elim ty
+  [#o #a normalize @tval
+  |#ty1 #ty2 #Hind1 #Hind2 normalize * #v #Hv @tvec
+    [<Hv >length_map >length_map //
+    |#M elim v 
+      [normalize @False_ind |#a #v1 #Hind3 * [#eqM >eqM @Hind2 |@Hind3]]
+    ]
+  ]
+qed.
+
+lemma inv_rel: βˆ€O,D,G,n,ty.
+  TJ O D G (Rel O D n) ty β†’ βˆƒG1,G2.|G1|=n∧G=G1@ty::G2.
+#O #D #G #n #ty #Hrel inversion Hrel
+  [#G1 #o #a #_ #H destruct 
+  |#G1 #ty1 #G2 #n1 #H1 #H2 #H3 #H4 destruct %{G1} %{G2} /2/ 
+  |#G1 #M0 #N #ty1 #ty2 #_ #_ #_ #_ #_ #H destruct
+  |#G1 #M0 #ty4 #ty5 #HM0 #_ #_ #H #H1 destruct 
+  |#G1 #v #ty3 #ty4 #_ #_ #_ #_ #H destruct 
+  ]
+qed.
+      
+lemma inv_tlambda: βˆ€O,D,G,M,ty1,ty2,ty3.
+  TJ O D G (Lambda O D ty1 M) (arrow O ty2 ty3) β†’ 
+  ty1 = ty2 βˆ§ TJ O D (ty2::G) M ty3.
+#O #D #G #M #ty1 #ty2 #ty3 #Hlam inversion Hlam
+  [#G1 #o #a #_ #H destruct 
+  |#G1 #ty #G2 #n #_ #_ #H destruct
+  |#G1 #M0 #N #ty1 #ty2 #_ #_ #_ #_ #_ #H destruct
+  |#G1 #M0 #ty4 #ty5 #HM0 #_ #_ #H #H1 destruct % //
+  |#G1 #v #ty3 #ty4 #_ #_ #_ #_ #H destruct 
+  ]
+qed.
+
+lemma inv_tvec: βˆ€O,D,G,v,ty1,ty2,ty3.
+   TJ O D G (Vec O D ty1 v) (arrow O ty2 ty3) β†’
+  (|v| = |enum (FinSet_of_FType O D ty1)|) βˆ§
+  (βˆ€M. mem ? M v β†’ TJ O D G M ty3).
+#O #D #G #v #ty1 #ty2 #ty3 #Hvec inversion Hvec
+  [#G #o #a #_ #H destruct 
+  |#G1 #ty #G2 #n #_ #_ #H destruct
+  |#G1 #M0 #N #ty1 #ty2 #_ #_ #_ #_ #_ #H destruct
+  |#G1 #M0 #ty4 #ty5 #HM0 #_ #_ #H #H1 destruct 
+  |#G1 #v1 #ty4 #ty5 #Hv #Hmem #_ #_ #H #H1 destruct % // @Hmem 
+  ]
+qed.
+
+(* could be generalized *)
+lemma weak_rel: βˆ€O,D,G1,G2,ty1,ty2,n. length ? G1 < n β†’ 
+   TJ O D (G1@G2) (Rel O D n) ty1 β†’
+   TJ O D (G1@ty2::G2) (Rel O D (S n)) ty1.
+#O #D #G1 #G2 #ty1 #ty2 #n #HG1 #Hrel lapply (inv_rel β€¦ Hrel)
+* #G3 * #G4 * #H1 #H2 lapply (compare_append β€¦ H2)
+* #G5 *
+  [* #H3 @False_ind >H3 in HG1; >length_append >H1 #H4
+   @(absurd β€¦ H4) @le_to_not_lt //
+  |* #H3 #H4 >H4 >append_cons <associative_append @trel
+   >length_append >length_append <H1 >H3 >length_append normalize 
+   >plus_n_Sm >associative_plus @eq_f //
+  ]
+qed.
+
+lemma strength_rel: βˆ€O,D,G1,G2,ty1,ty2,n. length ? G1 < n β†’ 
+   TJ O D (G1@ty2::G2) (Rel O D n) ty1 β†’
+   TJ O D (G1@G2) (Rel O D (n-1)) ty1.
+#O #D #G1 #G2 #ty1 #ty2 #n #HG1 #Hrel lapply (inv_rel β€¦ Hrel)
+* #G3 * #G4 * #H1 #H2 lapply (compare_append β€¦ H2)
+* #G5 *
+  [* #H3 @False_ind >H3 in HG1; >length_append >H1 #H4
+   @(absurd β€¦ H4) @le_to_not_lt //
+  |lapply G5 -G5 * 
+    [>append_nil normalize * #H3 #H4 destruct @False_ind @(absurd β€¦ HG1) 
+     @le_to_not_lt //
+    |#ty3 #G5 * #H3 normalize #H4 destruct (H4) <associative_append @trel
+     <H1 >H3 >length_append >length_append normalize <plus_minus_associative //
+    ]
+  ]
+qed.
+
+lemma no_matter: βˆ€O,D,G,N,tyN. 
+  TJ O D G N tyN β†’  βˆ€G1,G2,G3.G=G1@G2 β†’ is_closed O D (|G1|) N β†’
+    TJ O D (G1@G3) N tyN.    
+#O #D #G #N #tyN #HN elim HN -HN -tyN -N -G 
+  [#G #o #a #G1 #G2 #G3 #_ #_ @tval 
+  |#G #ty #G2 #n #HG #G3 #G4 #G5 #H #HNC normalize 
+   lapply (is_closed_rel β€¦ HNC) #Hlt lapply (compare_append β€¦ H) * #G6 *
+    [* #H1 @False_ind @(absurd ? Hlt) @le_to_not_lt <HG >H1 >length_append // 
+    |* cases G6
+      [>append_nil normalize #H1 @False_ind 
+       @(absurd ? Hlt) @le_to_not_lt <HG >H1 //
+      |#ty1 #G7 #H1 normalize #H2 destruct >associative_append @trel //
+      ]
+    ]
+  |#G #M #N #ty1 #ty2 #HM #HN #HindM #HindN #G1 #G2 #G3 
+   #Heq #Hc lapply (is_closed_app β€¦ Hc) -Hc * #HMc #HNc  
+   @(tapp β€¦ (HindM β€¦ Heq HMc) (HindN β€¦ Heq HNc))
+  |#G #M #ty1 #ty2 #HM #HindM #G1 #G2 #G3 #Heq #Hc
+   lapply (is_closed_lam β€¦ Hc) -Hc #HMc 
+   @tlambda @(HindM (ty1::G1) G2) [>Heq // |@HMc]
+  |#G #v #ty1 #ty2 #Hlen #Hv #Hind #G1 #G2 #G3 #H1 #Hc @tvec 
+    [>length_map // 
+    |#M #Hmem @Hind // lapply (is_closed_vec β€¦ Hc) #Hvc @Hvc //
+    ]
+  ]
+qed.
+
+lemma nth_spec: βˆ€A,a,d,l1,l2,n. |l1| = n β†’ nth n A (l1@a::l2) d = a.
+#A #a #d #l1 elim l1 normalize
+  [#l2 #n #Hn <Hn  //
+  |#b #tl #Hind #l2 #m #Hm <Hm normalize @Hind //
+  ]
+qed.
+             
+lemma wt_subst_gen: βˆ€O,D,G,M,tyM. 
+  TJ O D G M tyM β†’ 
+   βˆ€G1,G2,N,tyN.G=(G1@tyN::G2) β†’
+    TJ O D G2 N tyN β†’ is_closed O D 0 N β†’
+     TJ O D (G1@G2) (subst O D M (|G1|) N) tyM.
+#O #D #G #M #tyM #HM elim HM -HM -tyM -M -G
+  [#G #o #a #G1 #G2 #N #tyN #_ #HG #_ normalize @tval
+  |#G #ty #G2 #n #Hlen #G21 #G22 #N #tyN #HG #HN #HNc
+   normalize cases (true_or_false (leb (|G21|) n))
+    [#H >H cases (le_to_or_lt_eq β€¦ (leb_true_to_le β€¦ H))
+      [#ltn >(not_eq_to_eqb_false β€¦ (lt_to_not_eq β€¦ ltn)) normalize
+       lapply (compare_append β€¦ HG) * #G3 *
+        [* #HG1 #HG2 @(strength_rel β€¦ tyN β€¦ ltn) <HG @trel @Hlen
+        |* #HG >HG in ltn; >length_append #ltn @False_ind 
+         @(absurd β€¦ ltn) @le_to_not_lt >Hlen //
+        ] 
+      |#HG21 >(eq_to_eqb_true β€¦ HG21) 
+       cut (ty = tyN) 
+        [<(nth_spec ? ty ty ? G2 β€¦ Hlen) >HG @nth_spec @HG21] #Hty >Hty
+       normalize <HG21 @(no_matter ????? HN []) //
+      ]
+    |#H >H normalize lapply (compare_append β€¦ HG) * #G3 *
+      [* #H1 @False_ind @(absurd ? Hlen) @sym_not_eq @lt_to_not_eq >H1
+       >length_append @(lt_to_le_to_lt n (|G21|)) // @not_le_to_lt
+       @(leb_false_to_not_le β€¦ H) 
+      |cases G3 
+        [>append_nil * #H1 @False_ind @(absurd ? Hlen) <H1 @sym_not_eq
+         @lt_to_not_eq @not_le_to_lt @(leb_false_to_not_le β€¦ H)
+        |#ty2 #G4 * #H1 normalize #H2 destruct >associative_append @trel //
+        ]
+      ]    
+    ]
+  |#G #M #N #ty1 #ty2 #HM #HN #HindM #HindN #G1 #G2 #N0 #tyN0 #eqG
+   #HN0 #Hc normalize @(tapp β€¦ ty1) 
+    [@(HindM β€¦ eqG HN0 Hc) |@(HindN β€¦ eqG HN0 Hc)]
+  |#G #M #ty1 #ty2 #HM #HindM #G1 #G2 #N0 #tyN0 #eqG
+   #HN0 #Hc normalize @(tlambda β€¦ ty1) @(HindM (ty1::G1) β€¦ HN0) // >eqG //
+  |#G #v #ty1 #ty2 #Hlen #Hv #Hind #G1 #G2 #N0 #tyN0 #eqG
+   #HN0 #Hc normalize @(tvec β€¦ ty1) 
+    [>length_map @Hlen
+    |#M #Hmem lapply (mem_map ????? Hmem) * #a * -Hmem #Hmem #eqM <eqM
+     @(Hind β€¦ Hmem β€¦ eqG HN0 Hc) 
+    ]
+  ]
+qed.
+
+lemma wt_subst: βˆ€O,D,M,N,G,ty1,ty2. 
+  TJ O D (ty1::G) M ty2 β†’ 
+  TJ O D G N ty1 β†’ is_closed O D 0 N β†’
+  TJ O D G (subst O D M 0 N) ty2.
+#O #D #M #N #G #ty1 #ty2 #HM #HN #Hc @(wt_subst_gen β€¦(ty1::G) β€¦ [ ] β€¦ HN) //
+qed.
+
+lemma subject_reduction: βˆ€O,D,M,M1,G,ty. 
+  TJ O D G M ty β†’ red O D M M1 β†’ TJ O D G M1 ty.
+#O #D #M #M1 #G #ty #HM lapply M1 -M1 elim HM  -HM -ty -G -M
+  [#G #o #a #M1 #Hval elim (red_val ????? Hval)
+  |#G #ty #G1 #n #_ #M1 #Hrel elim (red_rel ???? Hrel) 
+  |#G #M #N #ty1 #ty2 #HM #HN #HindM #HindN #M1 #Hred inversion Hred
+    [#P #M0 #N0 #Hc #H1 destruct (H1) #HM1 @(wt_subst β€¦ HN) //
+     @(proj2 β€¦ (inv_tlambda β€¦ HM))
+    |#ty #v #a #M0 #Ha #H1 #H2 destruct @(proj2 β€¦ (inv_tvec β€¦ HM))
+     @(assoc_to_mem β€¦ Ha)
+    |#M2 #M3 #N0 #Hredl #_ #H1 destruct (H1) #eqM1 @(tapp β€¦ HN) @HindM @Hredl
+    |#M2 #M3 #N0 #Hredr #_ #H1 destruct (H1) #eqM1 @(tapp β€¦ HM) @HindN @Hredr
+    |#ty #N0 #N1 #_ #_ #H1 destruct (H1)
+    |#ty #M0 #H1 destruct (H1)
+    |#ty #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1)
+    ]
+  |#G #P #ty1 #ty2 #HP #Hind #M1 #Hred lapply(red_lambda ????? Hred) *
+    [* #P1 * #HredP #HM1 >HM1 @tlambda @Hind //
+    |#HM1 >HM1 @tvec // #N #HN lapply(mem_map ????? HN) 
+     * #a * #mema #eqN <eqN -eqN @(wt_subst β€¦HP) // @wt_to_T
+    ]
+  |#G #v #ty1 #ty2 #Hlen #Hv #Hind #M1 #Hred lapply(red_vec ????? Hred)
+   * #N * #N1 * #v1 * #v2 * * #H1 #H2 #H3 >H3 @tvec 
+    [<Hlen >H2 >length_append >length_append @eq_f //
+    |#M2 #Hmem cases (mem_append ???? Hmem) -Hmem #Hmem
+      [@Hv >H2 @mem_append_l1 //
+      |cases Hmem 
+        [#HM2 >HM2 -HM2 @(Hind N β€¦ H1) >H2 @mem_append_l2 %1 //
+        |-Hmem #Hmem @Hv >H2 @mem_append_l2 %2 //
+        ]
+      ]
+    ]
+  ]
+qed.
+    
diff --git a/matita/matita/broken_lib/reverse_complexity/big_O.ma b/matita/matita/broken_lib/reverse_complexity/big_O.ma
new file mode 100644 (file)
index 0000000..833572e
--- /dev/null
@@ -0,0 +1,89 @@
+
+include "arithmetics/nat.ma".
+include "basics/sets.ma".
+
+(******************************** big O notation ******************************)
+
+(*  O f g means g βˆˆ O(f) *)
+definition O: relation (natβ†’nat) β‰
+  Ξ»f,g. βˆƒc.βˆƒn0.βˆ€n. n0 β‰€ n β†’ g n β‰€ c* (f n).
+  
+lemma O_refl: βˆ€s. O s s.
+#s %{1} %{0} #n #_ >commutative_times <times_n_1 @le_n qed.
+
+lemma O_trans: βˆ€s1,s2,s3. O s2 s1 β†’ O s3 s2 β†’ O s3 s1. 
+#s1 #s2 #s3 * #c1 * #n1 #H1 * #c2 * # n2 #H2 %{(c1*c2)}
+%{(max n1 n2)} #n #Hmax 
+@(transitive_le β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
+>associative_times @le_times [//|@H2 @(le_maxr β€¦ Hmax)]
+qed.
+
+lemma sub_O_to_O: βˆ€s1,s2. O s1 βŠ† O s2 β†’ O s2 s1.
+#s1 #s2 #H @H // qed.
+
+lemma O_to_sub_O: βˆ€s1,s2. O s2 s1 β†’ O s1 βŠ† O s2.
+#s1 #s2 #H #g #Hg @(O_trans β€¦ H) // qed. 
+
+lemma le_to_O: βˆ€s1,s2. (βˆ€x.s1 x β‰€ s2 x) β†’ O s2 s1.
+#s1 #s2 #Hle %{1} %{0} #n #_ normalize <plus_n_O @Hle
+qed.
+
+definition sum_f β‰ Ξ»f,g:natβ†’nat.Ξ»n.f n + g n.
+interpretation "function sum" 'plus f g = (sum_f f g).
+
+lemma O_plus: βˆ€f,g,s. O s f β†’ O s g β†’ O s (f+g).
+#f #g #s * #cf * #nf #Hf * #cg * #ng #Hg
+%{(cf+cg)} %{(max nf ng)} #n #Hmax normalize 
+>distributive_times_plus_r @le_plus 
+  [@Hf @(le_maxl β€¦ Hmax) |@Hg @(le_maxr β€¦ Hmax) ]
+qed.
+lemma O_plus_l: βˆ€f,s1,s2. O s1 f β†’ O (s1+s2) f.
+#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
+@(transitive_le β€¦ (Os1f n lean)) @le_times //
+qed.
+
+lemma O_plus_r: βˆ€f,s1,s2. O s2 f β†’ O (s1+s2) f.
+#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
+@(transitive_le β€¦ (Os1f n lean)) @le_times //
+qed.
+
+lemma O_absorbl: βˆ€f,g,s. O s f β†’ O f g β†’ O s (g+f).
+#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
+qed.
+
+lemma O_absorbr: βˆ€f,g,s. O s f β†’ O f g β†’ O s (f+g).
+#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
+qed.
+
+lemma O_times_c: βˆ€f,c. O f (Ξ»x:β„•.c*f x).
+#f #c %{c} %{0} //
+qed.
+
+lemma O_ext2: βˆ€f,g,s. O s f β†’ (βˆ€x.f x = g x) β†’ O s g.
+#f #g #s * #c * #a #Osf #eqfg %{c} %{a} #n #lean <eqfg @Osf //
+qed.    
+
+
+definition not_O β‰ Ξ»f,g.βˆ€c,n0.βˆƒn. n0 β‰€ n βˆ§ c* (f n) < g n .
+
+(* this is the only classical result *)
+axiom not_O_def: βˆ€f,g. Β¬ O f g β†’ not_O f g.
+
+(******************************* small O notation *****************************)
+
+(*  o f g means g βˆˆ o(f) *)
+definition o: relation (natβ†’nat) β‰
+  Ξ»f,g.βˆ€c.βˆƒn0.βˆ€n. n0 β‰€ n β†’ c * (g n) < f n.
+  
+lemma o_irrefl: βˆ€s. Β¬ o s s.
+#s % #oss cases (oss 1) #n0 #H @(absurd ? (le_n (s n0))) 
+@lt_to_not_le >(times_n_1 (s n0)) in βŠ’ (?%?); >commutative_times @H //
+qed.
+
+lemma o_trans: βˆ€s1,s2,s3. o s2 s1 β†’ o s3 s2 β†’ o s3 s1. 
+#s1 #s2 #s3 #H1 #H2 #c cases (H1 c) #n1 -H1 #H1 cases (H2 1) #n2 -H2 #H2
+%{(max n1 n2)} #n #Hmax 
+@(transitive_lt β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
+>(times_n_1 (s2 n)) in βŠ’ (?%?); >commutative_times @H2 @(le_maxr β€¦ Hmax)
+qed.
diff --git a/matita/matita/broken_lib/reverse_complexity/gap.ma b/matita/matita/broken_lib/reverse_complexity/gap.ma
new file mode 100644 (file)
index 0000000..2c8b6e9
--- /dev/null
@@ -0,0 +1,251 @@
+
+include "arithmetics/minimization.ma".
+include "arithmetics/bigops.ma".
+include "arithmetics/pidgeon_hole.ma".
+include "arithmetics/iteration.ma".
+
+(************************** notation for miminimization ***********************)
+
+(* an alternative defintion of minimization 
+definition Min β‰ Ξ»a,f. 
+  \big[min,a]_{i < a | f i} i. *)
+
+notation "ΞΌ_{ ident i < n } p" 
+  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
+
+notation "ΞΌ_{ ident i β‰€ n } p" 
+  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
+  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
+  
+lemma f_min_true: βˆ€f,a,b.
+  (βˆƒi. a β‰€ i βˆ§ i β‰€ b βˆ§ f i = true) β†’ f (ΞΌ_{i βˆˆ[a,b]} (f i)) = true.
+#f #a #b * #i * * #Hil #Hir #Hfi @(f_min_true β€¦ (Ξ»x. f x)) <plus_minus_m_m 
+  [%{i} % // % [@Hil |@le_S_S @Hir]|@le_S @(transitive_le β€¦ Hil Hir)]
+qed.
+
+lemma min_up: βˆ€f,a,b.
+  (βˆƒi. a β‰€ i βˆ§ i β‰€ b βˆ§ f i = true) β†’ ΞΌ_{i βˆˆ[a,b]}(f i) β‰€ b. 
+#f #a #b * #i * * #Hil #Hir #Hfi @le_S_S_to_le
+cut ((S b) = S b - a + a) [@plus_minus_m_m @le_S @(transitive_le β€¦ Hil Hir)]
+#Hcut >Hcut in βŠ’ (??%); @lt_min %{i} % // % [@Hil |<Hcut @le_S_S @Hir]
+qed.
+
+(*************************** Kleene's predicate *******************************)
+
+axiom U: nat β†’ nat β†’nat β†’ option nat.
+
+axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
+  U i x n = Some ? y β†’ U i x m = Some ? y.
+  
+lemma unique_U: βˆ€i,x,n,m,yn,ym.
+  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
+#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
+  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
+  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
+   >Hn #HS destruct (HS) //
+  ]
+qed.
+
+definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y.
+
+notation "〈i,xβŒͺ β†“ r" with precedence 60 for @{terminate $i $x $r}.
+
+lemma terminate_dec: βˆ€i,x,n. βŒ©i,xβŒͺ β†“ n βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ n.
+#i #x #n normalize cases (U i x n)
+  [%2 % * #y #H destruct|#y %1 %{y} //]
+qed. 
+
+definition termb β‰ Ξ»i,x,t. 
+  match U i x t with [None β‡’ false |Some y β‡’ true].
+
+lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ βŒ©i,xβŒͺ β†“ t.
+#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
+qed.    
+
+lemma term_to_termb_true: βˆ€i,x,t. βŒ©i,xβŒͺ β†“ t β†’ termb i x t = true.
+#i #x #t * #y #H normalize >H // 
+qed.    
+
+lemma decidable_test : βˆ€n,x,r,r1.
+       (βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ r1) βˆ¨ 
+       (βˆƒi. i < n βˆ§ (Β¬ βŒ©i,xβŒͺ β†“ r βˆ§ βŒ©i,xβŒͺ β†“ r1)).
+#n #x #r1 #r2
+  cut (βˆ€i0.decidable ((〈i0,xβŒͺ↓r1) βˆ¨ Β¬ βŒ©i0,xβŒͺ β†“ r2)) 
+    [#j @decidable_or [@terminate_dec |@decidable_not @terminate_dec ]] #Hdec
+ cases(decidable_forall ? Hdec n) 
+  [#H %1 @H  
+  |#H %2 cases (not_forall_to_exists β€¦ Hdec H) #j * #leji #Hj
+   %{j} % // % 
+    [@(not_to_not β€¦ Hj) #H %1 @H 
+    |cases (terminate_dec j x r2) // #H @False_ind cases Hj -Hj #Hj
+     @Hj %2 @H
+  ]
+qed.
+
+(**************************** the gap theorem *********************************)
+definition gapP β‰ Ξ»n,x,g,r. βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g r.
+
+lemma gapP_def : βˆ€n,x,g,r. 
+  gapP n x g r = βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g r.
+// qed.
+
+lemma upper_bound_aux: βˆ€g,b,n,x. (βˆ€x. x β‰€ g x) β†’ βˆ€k.
+  (βˆƒj.j < k βˆ§
+    (βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ g^j b βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g^(S j) b)) βˆ¨
+  βˆƒl. |l| = k βˆ§ unique ? l βˆ§ βˆ€i. i βˆˆ l β†’ i < n βˆ§ βŒ©i,xβŒͺ β†“ g^k b .
+#g#b #n #x #Hg #k elim k 
+  [%2 %{([])} normalize % [% //|#x @False_ind]
+  |#k0 * 
+    [* #j * #lej #H %1 %{j} % [@le_S // | @H ]
+    |* #l * * #Hlen #Hunique #Hterm
+     cases (decidable_test n x (g^k0 b) (g^(S k0) b))
+      [#Hcase %1 %{k0} % [@le_n | @Hcase]
+      |* #j * #ltjn * #H1 #H2 %2 
+       %{(j::l)} % 
+        [ % [normalize @eq_f @Hlen] whd % // % #H3
+         @(absurd ?? H1) @(proj2 β€¦ (Hterm β€¦)) @H3
+        |#x *
+          [#eqxj >eqxj % // 
+          |#Hmemx cases(Hterm β€¦ Hmemx) #lexn * #y #HU
+           % [@lexn] %{y} @(monotonic_U ?????? HU) @Hg
+          ]
+        ]
+      ]
+    ]
+  ]
+qed.
+       
+lemma upper_bound: βˆ€g,b,n,x. (βˆ€x. x β‰€ g x) β†’ βˆƒr. 
+  (* b β‰€ r βˆ§ r β‰€ g^n b βˆ§ βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g r. *)
+  b β‰€ r βˆ§ r β‰€ g^n b βˆ§ gapP n x g r. 
+#g #b #n #x #Hg 
+cases (upper_bound_aux g b n x Hg n)
+  [* #j * #Hj #H %{(g^j b)} % [2: @H] % [@le_iter //]
+   @monotonic_iter2 // @lt_to_le //
+  |* #l * * #Hlen #Hunique #Hterm %{(g^n b)} % 
+    [% [@le_iter // |@le_n]] 
+   #i #lein %1 @(proj2 β€¦ (Hterm ??)) 
+   @(eq_length_to_mem_all β€¦ Hlen Hunique β€¦ lein)
+   #x #memx @(proj1  β€¦ (Hterm ??)) //
+  ]
+qed. 
+
+definition gapb β‰ Ξ»n,x,g,r.
+  \big[andb,true]_{i < n} ((termb i x r) βˆ¨ Β¬(termb i x (g r))). 
+  
+lemma gapb_def : βˆ€n,x,g,r. gapb n x g r =
+  \big[andb,true]_{i < n} ((termb i x r) βˆ¨ Β¬(termb i x (g r))). 
+// qed.
+
+lemma gapb_true_to_gapP : βˆ€n,x,g,r. 
+  gapb n x g r = true β†’ βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬(〈i,xβŒͺ β†“ (g r)).
+#n #x #g #r elim n 
+  [>gapb_def >bigop_Strue //
+   #H #i #lti0 @False_ind @(absurd β€¦ lti0) @le_to_not_lt //
+  |#m #Hind >gapb_def >bigop_Strue //
+   #H #i #leSm cases (le_to_or_lt_eq β€¦ leSm)
+    [#lem @Hind [@(andb_true_r β€¦ H)|@le_S_S_to_le @lem]
+    |#eqi >(injective_S β€¦ eqi) lapply (andb_true_l β€¦ H) -H #H cases (orb_true_l β€¦ H) -H
+      [#H %1 @termb_true_to_term //
+      |#H %2 % #H1 >(term_to_termb_true β€¦  H1) in H; normalize #H destruct
+      ]
+    ]
+  ]
+qed.
+
+lemma gapP_to_gapb_true : βˆ€n,x,g,r. 
+  (βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬(〈i,xβŒͺ β†“ (g r))) β†’ gapb n x g r = true. 
+#n #x #g #r elim n //
+#m #Hind #H >gapb_def >bigop_Strue // @true_to_andb_true
+  [cases (H m (le_n β€¦)) 
+    [#H2 @orb_true_r1 @term_to_termb_true //
+    |#H2 @orb_true_r2 @sym_eq @noteq_to_eqnot @sym_not_eq 
+     @(not_to_not β€¦ H2) @termb_true_to_term 
+    ]
+  |@Hind #i0 #lei0 @H @le_S //
+  ]
+qed.
+
+
+(* the gap function *)
+let rec gap g n on n β‰
+  match n with 
+  [ O β‡’ 1
+  | S m β‡’ let b β‰ gap g m in ΞΌ_{i βˆˆ [b,g^n b]} (gapb n n g i)
+  ].
+  
+lemma gapS: βˆ€g,m. 
+  gap g (S m) = 
+    (let b β‰ gap g m in 
+      ΞΌ_{i βˆˆ [b,g^(S m) b]} (gapb (S m) (S m) g i)).
+// qed.
+
+lemma upper_bound_gapb: βˆ€g,m. (βˆ€x. x β‰€ g x) β†’ 
+  βˆƒr:β„•.gap g m β‰€ r βˆ§ r β‰€ g^(S m) (gap g m) βˆ§ gapb (S m) (S m) g r = true.
+#g #m #leg 
+lapply (upper_bound g (gap g m) (S m) (S m) leg) * #r * *
+#H1 #H2 #H3 %{r} % 
+  [% // |@gapP_to_gapb_true @H3]
+qed.
+   
+lemma gapS_true: βˆ€g,m. (βˆ€x. x β‰€g x) β†’ gapb (S m) (S m) g (gap g (S m)) = true.
+#g #m #leg @(f_min_true (gapb (S m) (S m) g)) @upper_bound_gapb //
+qed.
+  
+theorem gap_theorem: βˆ€g,i.(βˆ€x. x β‰€ g x)β†’βˆƒk.βˆ€n.k < n β†’ 
+   βŒ©i,nβŒͺ β†“ (gap g n) βˆ¨ Β¬ βŒ©i,nβŒͺ β†“ (g (gap g n)).
+#g #i #leg %{i} * 
+  [#lti0 @False_ind @(absurd ?? (not_le_Sn_O i) ) //
+  |#m #leim lapply (gapS_true g m leg) #H
+   @(gapb_true_to_gapP β€¦ H) //
+  ]
+qed.
+
+(* an upper bound *)
+
+let rec sigma n β‰ 
+  match n with 
+  [ O β‡’ 0 | S m β‡’ n + sigma m ].
+  
+lemma gap_bound: βˆ€g. (βˆ€x. x β‰€ g x) β†’ (monotonic ? le g) β†’ 
+  βˆ€n.gap g n β‰€ g^(sigma n) 1.
+#g #leg #gmono #n elim n 
+  [normalize //
+  |#m #Hind >gapS @(transitive_le ? (g^(S m) (gap g m)))
+    [@min_up @upper_bound_gapb // 
+    |@(transitive_le ? (g^(S m) (g^(sigma m) 1)))
+      [@monotonic_iter // |>iter_iter >commutative_plus @le_n
+    ]
+  ]
+qed.
+
+lemma gap_bound2: βˆ€g. (βˆ€x. x β‰€ g x) β†’ (monotonic ? le g) β†’ 
+  βˆ€n.gap g n β‰€ g^(n*n) 1.
+#g #leg #gmono #n elim n 
+  [normalize //
+  |#m #Hind >gapS @(transitive_le ? (g^(S m) (gap g m)))
+    [@min_up @upper_bound_gapb // 
+    |@(transitive_le ? (g^(S m) (g^(m*m) 1)))
+      [@monotonic_iter //
+      |>iter_iter @monotonic_iter2 [@leg | normalize <plus_n_Sm @le_S_S //
+    ]
+  ]
+qed.
+
+(*
+axiom universal: βˆƒu.βˆ€i,x,y. 
+  βˆƒn. U u βŒ©i,xβŒͺ n = Some y β†” βˆƒm.U i x m = Some y. *)
+
+   
+
+
+
+
+
+
+
+
+
+
diff --git a/matita/matita/broken_lib/reverse_complexity/hierarchy.ma b/matita/matita/broken_lib/reverse_complexity/hierarchy.ma
new file mode 100644 (file)
index 0000000..a621b55
--- /dev/null
@@ -0,0 +1,565 @@
+
+include "arithmetics/nat.ma".
+include "arithmetics/log.ma".
+(* include "arithmetics/ord.ma". *)
+include "arithmetics/bigops.ma".
+include "arithmetics/bounded_quantifiers.ma".
+include "arithmetics/pidgeon_hole.ma".
+include "basics/sets.ma".
+include "basics/types.ma".
+
+(************************************ MAX *************************************)
+notation "Max_{ ident i < n | p } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident i < n } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident j βˆˆ [a,b[ } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+  
+notation "Max_{ ident j βˆˆ [a,b[ | p } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+
+lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
+#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
+  [cases (true_or_false (leb b c )) #lebc >lebc normalize
+    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
+    |>leab //
+    ]
+  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
+   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
+   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
+  ]
+qed.
+
+lemma Max0 : βˆ€n. max 0 n = n.
+// qed.
+
+lemma Max0r : βˆ€n. max n 0 = n.
+#n >commutative_max //
+qed.
+
+definition MaxA β‰ 
+  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
+
+definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
+
+lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
+  f a β‰€  Max_{i < n | p i}(f i).
+#f #p #n #a #ltan #pa 
+>(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
+qed.
+
+lemma Max_le: βˆ€f,p,n,b. 
+  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
+#f #p #n elim n #b #H // 
+#b0 #H1 cases (true_or_false (p b)) #Hb
+  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
+  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
+  ]
+qed.
+
+(******************************** big O notation ******************************)
+
+(*  O f g means g βˆˆ O(f) *)
+definition O: relation (natβ†’nat) β‰
+  Ξ»f,g. βˆƒc.βˆƒn0.βˆ€n. n0 β‰€ n β†’ g n β‰€ c* (f n).
+  
+lemma O_refl: βˆ€s. O s s.
+#s %{1} %{0} #n #_ >commutative_times <times_n_1 @le_n qed.
+
+lemma O_trans: βˆ€s1,s2,s3. O s2 s1 β†’ O s3 s2 β†’ O s3 s1. 
+#s1 #s2 #s3 * #c1 * #n1 #H1 * #c2 * # n2 #H2 %{(c1*c2)}
+%{(max n1 n2)} #n #Hmax 
+@(transitive_le β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
+>associative_times @le_times [//|@H2 @(le_maxr β€¦ Hmax)]
+qed.
+
+lemma sub_O_to_O: βˆ€s1,s2. O s1 βŠ† O s2 β†’ O s2 s1.
+#s1 #s2 #H @H // qed.
+
+lemma O_to_sub_O: βˆ€s1,s2. O s2 s1 β†’ O s1 βŠ† O s2.
+#s1 #s2 #H #g #Hg @(O_trans β€¦ H) // qed. 
+
+definition sum_f β‰ Ξ»f,g:natβ†’nat.Ξ»n.f n + g n.
+interpretation "function sum" 'plus f g = (sum_f f g).
+
+lemma O_plus: βˆ€f,g,s. O s f β†’ O s g β†’ O s (f+g).
+#f #g #s * #cf * #nf #Hf * #cg * #ng #Hg
+%{(cf+cg)} %{(max nf ng)} #n #Hmax normalize 
+>distributive_times_plus_r @le_plus 
+  [@Hf @(le_maxl β€¦ Hmax) |@Hg @(le_maxr β€¦ Hmax) ]
+qed.
+lemma O_plus_l: βˆ€f,s1,s2. O s1 f β†’ O (s1+s2) f.
+#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
+@(transitive_le β€¦ (Os1f n lean)) @le_times //
+qed.
+
+lemma O_plus_r: βˆ€f,s1,s2. O s2 f β†’ O (s1+s2) f.
+#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
+@(transitive_le β€¦ (Os1f n lean)) @le_times //
+qed.
+
+lemma O_absorbl: βˆ€f,g,s. O s f β†’ O f g β†’ O s (g+f).
+#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
+qed.
+
+lemma O_absorbr: βˆ€f,g,s. O s f β†’ O f g β†’ O s (f+g).
+#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
+qed.
+
+(* 
+lemma O_ff: βˆ€f,s. O s f β†’ O s (f+f).
+#f #s #Osf /2/ 
+qed. *)
+
+lemma O_ext2: βˆ€f,g,s. O s f β†’ (βˆ€x.f x = g x) β†’ O s g.
+#f #g #s * #c * #a #Osf #eqfg %{c} %{a} #n #lean <eqfg @Osf //
+qed.    
+
+
+definition not_O β‰ Ξ»f,g.βˆ€c,n0.βˆƒn. n0 β‰€ n βˆ§ c* (f n) < g n .
+
+(* this is the only classical result *)
+axiom not_O_def: βˆ€f,g. Β¬ O f g β†’ not_O f g.
+
+(******************************* small O notation *****************************)
+
+(*  o f g means g βˆˆ o(f) *)
+definition o: relation (natβ†’nat) β‰
+  Ξ»f,g.βˆ€c.βˆƒn0.βˆ€n. n0 β‰€ n β†’ c * (g n) < f n.
+  
+lemma o_irrefl: βˆ€s. Β¬ o s s.
+#s % #oss cases (oss 1) #n0 #H @(absurd ? (le_n (s n0))) 
+@lt_to_not_le >(times_n_1 (s n0)) in βŠ’ (?%?); >commutative_times @H //
+qed.
+
+lemma o_trans: βˆ€s1,s2,s3. o s2 s1 β†’ o s3 s2 β†’ o s3 s1. 
+#s1 #s2 #s3 #H1 #H2 #c cases (H1 c) #n1 -H1 #H1 cases (H2 1) #n2 -H2 #H2
+%{(max n1 n2)} #n #Hmax 
+@(transitive_lt β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
+>(times_n_1 (s2 n)) in βŠ’ (?%?); >commutative_times @H2 @(le_maxr β€¦ Hmax)
+qed.
+
+
+(*********************************** pairing **********************************) 
+
+axiom pair: nat β†’nat β†’nat.
+axiom fst : nat β†’ nat.
+axiom snd : nat β†’ nat.
+axiom fst_pair: βˆ€a,b. fst (pair a b) = a.
+axiom snd_pair: βˆ€a,b. snd (pair a b) = b. 
+
+interpretation "abstract pair" 'pair f g = (pair f g).
+
+(************************ basic complexity notions ****************************)
+
+(* u is the deterministic configuration relation of the universal machine (one 
+   step) 
+
+axiom u: nat β†’ option nat.
+
+let rec U c n on n β‰ 
+  match n with  
+  [ O β‡’ None ?
+  | S m β‡’ match u c with 
+    [ None β‡’ Some ? c (* halting case *)
+    | Some c1 β‡’ U c1 m
+    ]
+  ].
+lemma halt_U: βˆ€i,n,y. u i = None ? β†’ U i n = Some ? y β†’ y = i.
+#i #n #y #H cases n
+  [normalize #H1 destruct |#m normalize >H normalize #H1 destruct //]
+qed. 
+
+lemma Some_to_halt: βˆ€n,i,y. U i n = Some ? y β†’ u y = None ? .
+#n elim n
+  [#i #y normalize #H destruct (H)
+  |#m #Hind #i #y normalize 
+   cut (u i = None ? βˆ¨ βˆƒc. u i = Some ? c) 
+    [cases (u i) [/2/ | #c %2 /2/ ]] 
+   *[#H >H normalize #H1 destruct (H1) // |* #c #H >H normalize @Hind ]
+  ]
+qed. *)
+
+axiom U: nat β†’ nat β†’ nat β†’ option nat. 
+(*
+lemma monotonici_U: βˆ€y,n,m,i.
+  U i m = Some ? y β†’ U i (n+m) = Some ? y.
+#y #n #m elim m 
+  [#i normalize #H destruct 
+  |#p #Hind #i <plus_n_Sm normalize
+    cut (u i = None ? βˆ¨ βˆƒc. u i = Some ? c) 
+    [cases (u i) [/2/ | #c %2 /2/ ]] 
+   *[#H1 >H1 normalize // |* #c #H >H normalize #H1 @Hind //]
+  ]
+qed. *)
+
+axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
+  U i x n = Some ? y β†’ U i x m = Some ? y.
+(* #i #n #m #y #lenm #H >(plus_minus_m_m m n) // @monotonici_U //
+qed. *)
+
+(* axiom U: nat β†’ nat β†’ option nat. *)
+(* axiom monotonic_U: βˆ€i,n,m,y.n β‰€m β†’
+   U i n = Some ? y β†’ U i m = Some ? y. *)
+  
+lemma unique_U: βˆ€i,x,n,m,yn,ym.
+  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
+#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
+  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
+  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
+   >Hn #HS destruct (HS) //
+  ]
+qed.
+
+definition code_for β‰ Ξ»f,i.βˆ€x.
+  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
+
+definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y.
+notation "[i,x] β†“ r" with precedence 60 for @{terminate $i $x $r}.
+
+definition lang β‰ Ξ»i,x.βˆƒr,y. U i x r = Some ? y βˆ§ 0  < y. 
+
+lemma lang_cf :βˆ€f,i,x. code_for f i β†’ 
+  lang i x β†” βˆƒy.f x = Some ? y βˆ§ 0 < y.
+#f #i #x normalize #H %
+  [* #n * #y * #H1 #posy %{y} % // 
+   cases (H x) -H #m #H <(H (max n m)) [2:@(le_maxr β€¦ n) //]
+   @(monotonic_U β€¦ H1) @(le_maxl β€¦ m) //
+  |cases (H x) -H #m #Hm * #y #Hy %{m} %{y} >Hm // 
+  ]
+qed.
+
+(******************************* complexity classes ***************************)
+
+axiom size: nat β†’ nat.
+axiom of_size: nat β†’ nat.
+
+interpretation "size" 'card n = (size n).
+
+axiom size_of_size: βˆ€n. |of_size n| = n.
+axiom monotonic_size: monotonic ? le size.
+
+axiom of_size_max: βˆ€i,n. |i| = n β†’ i β‰€ of_size n.
+
+axiom size_fst : βˆ€n. |fst n| β‰€ |n|.
+
+definition size_f β‰ Ξ»f,n.Max_{i < S (of_size n) | eqb (|i|) n}|(f i)|.
+
+lemma size_f_def: βˆ€f,n. size_f f n = 
+  Max_{i < S (of_size n) | eqb (|i|) n}|(f i)|.
+// qed.
+
+(*
+definition Max_const : βˆ€f,p,n,a. a < n β†’ p a β†’
+  βˆ€n. f n = g n β†’
+  Max_{i < n | p n}(f n) = *)
+
+lemma size_f_size : βˆ€f,n. size_f (f βˆ˜ size) n = |(f n)|.
+#f #n @le_to_le_to_eq
+  [@Max_le #a #lta #Ha normalize >(eqb_true_to_eq  β€¦ Ha) //
+  |<(size_of_size n) in βŠ’ (?%?); >size_f_def
+   @(le_Max (Ξ»i.|f (|i|)|) ? (S (of_size n)) (of_size n) ??)
+    [@le_S_S // | @eq_to_eqb_true //]
+  ]
+qed.
+
+lemma size_f_id : βˆ€n. size_f (Ξ»x.x) n = n.
+#n @le_to_le_to_eq
+  [@Max_le #a #lta #Ha >(eqb_true_to_eq  β€¦ Ha) //
+  |<(size_of_size n) in βŠ’ (?%?); >size_f_def
+   @(le_Max (Ξ»i.|i|) ? (S (of_size n)) (of_size n) ??)
+    [@le_S_S // | @eq_to_eqb_true //]
+  ]
+qed.
+
+lemma size_f_fst : βˆ€n. size_f fst n β‰€ n.
+#n @Max_le #a #lta #Ha <(eqb_true_to_eq  β€¦ Ha) //
+qed.
+
+(* definition def β‰ Ξ»f:nat β†’ option nat.Ξ»x.βˆƒy. f x = Some ? y.*)
+
+(* C s i means that the complexity of i is O(s) *)
+
+definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ |x| β†’ βˆƒy. 
+  U i x (c*(s(|x|))) = Some ? y.
+
+definition CF β‰ Ξ»s,f.βˆƒi.code_for f i βˆ§ C s i.
+
+lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
+#f #g #s #Hext * #i * #Hcode #HC %{i} %
+  [#x cases (Hcode x) #a #H %{a} <Hext @H | //] 
+qed. 
+
+lemma monotonic_CF: βˆ€s1,s2,f. O s2 s1 β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f * #c1 * #a #H * #i * #Hcodef #HCs1 %{i} % //
+cases HCs1 #c2 * #b #H2 %{(c2*c1)} %{(max a b)} 
+#x #Hmax cases (H2 x ?) [2:@(le_maxr β€¦ Hmax)] #y #Hy
+%{y} @(monotonic_U β€¦Hy) >associative_times @le_times // @H @(le_maxl β€¦ Hmax)
+qed. 
+
+(************************** The diagonal language *****************************)
+
+(* the diagonal language used for the hierarchy theorem *)
+
+definition diag β‰ Ξ»s,i. 
+  U (fst i) i (s (|i|)) = Some ? 0. 
+
+lemma equiv_diag: βˆ€s,i. 
+  diag s i β†” [fst i,i] β†“ s (|i|) βˆ§ Β¬lang (fst i) i.
+#s #i %
+  [whd in βŠ’ (%β†’?); #H % [%{0} //] % * #x * #y *
+   #H1 #Hy cut (0 = y) [@(unique_U β€¦ H H1)] #eqy /2/
+  |* * #y cases y //
+   #y0 #H * #H1 @False_ind @H1 -H1 whd %{(s (|i|))} %{(S y0)} % //
+  ]
+qed.
+
+(* Let us define the characteristic function diag_cf for diag, and prove
+it correctness *)
+
+definition diag_cf β‰ Ξ»s,i.
+  match U (fst i) i (s (|i|)) with
+  [ None β‡’ None ?
+  | Some y β‡’ if (eqb y 0) then (Some ? 1) else (Some ? 0)].
+
+lemma diag_cf_OK: βˆ€s,x. diag s x β†” βˆƒy.diag_cf s x = Some ? y βˆ§ 0 < y.
+#s #x % 
+  [whd in βŠ’ (%β†’?); #H %{1} % // whd in βŠ’ (??%?); >H // 
+  |* #y * whd in βŠ’ (??%?β†’?β†’%); 
+   cases (U (fst x) x (s (|x|))) normalize
+    [#H destruct
+    |#x cases (true_or_false (eqb x 0)) #Hx >Hx 
+      [>(eqb_true_to_eq β€¦ Hx) // 
+      |normalize #H destruct #H @False_ind @(absurd ? H) @lt_to_not_le //  
+      ]
+    ]
+  ]
+qed.
+
+lemma diag_spec: βˆ€s,i. code_for (diag_cf s) i β†’ βˆ€x. lang i x β†” diag s x.
+#s #i #Hcode #x @(iff_trans  β€¦ (lang_cf β€¦ Hcode)) @iff_sym @diag_cf_OK
+qed. 
+
+(******************************************************************************)
+
+lemma absurd1: βˆ€P. iff P (Β¬ P) β†’False.
+#P * #H1 #H2 cut (Β¬P) [% #H2 @(absurd β€¦ H2) @H1 //] 
+#H3 @(absurd ?? H3) @H2 @H3 
+qed.
+
+(* axiom weak_pad : βˆ€a,βˆƒa0.βˆ€n. a0 < n β†’ βˆƒb. |〈a,bβŒͺ| = n. *)
+lemma weak_pad1 :βˆ€n,a.βˆƒb. n β‰€ βŒ©a,bβŒͺ. 
+#n #a 
+cut (βˆ€i.decidable (〈a,iβŒͺ < n))
+  [#i @decidable_le ] 
+   #Hdec cases(decidable_forall (Ξ»b. βŒ©a,bβŒͺ < n) Hdec n)
+  [#H cut (βˆ€i. i < n β†’ βˆƒb. b < n βˆ§ βŒ©a,bβŒͺ = i)
+    [@(injective_to_exists β€¦ H) //]
+   #Hcut %{n} @not_lt_to_le % #Han
+   lapply(Hcut ? Han) * #x * #Hx #Hx2 
+   cut (x = n) [//] #Hxn >Hxn in Hx; /2 by absurd/ 
+  |#H lapply(not_forall_to_exists β€¦ Hdec H) 
+   * #b * #H1 #H2 %{b} @not_lt_to_le @H2
+  ]
+qed. 
+
+lemma pad : βˆ€n,a. βˆƒb. n β‰€ |〈a,bβŒͺ|.
+#n #a cases (weak_pad1 (of_size n) a) #b #Hb 
+%{b} <(size_of_size n) @monotonic_size //
+qed.
+
+lemma o_to_ex: βˆ€s1,s2. o s1 s2 β†’ βˆ€i. C s2 i β†’
+  βˆƒb.[i, βŒ©i,bβŒͺ] β†“ s1 (|〈i,bβŒͺ|).
+#s1 #s2  #H #i * #c * #x0 #H1 
+cases (H c) #n0 #H2 cases (pad (max x0 n0) i) #b #Hmax
+%{b} cases (H1 βŒ©i,bβŒͺ ?)
+  [#z #H3 %{z} @(monotonic_U β€¦ H3) @lt_to_le @H2
+   @(le_maxr β€¦ Hmax)
+  |@(le_maxl β€¦ Hmax)
+  ]
+qed. 
+
+lemma diag1_not_s1: βˆ€s1,s2. o s1 s2 β†’ Β¬ CF s2 (diag_cf s1).
+#s1 #s2 #H1 % * #i * #Hcode_i #Hs2_i 
+cases (o_to_ex  β€¦ H1 ? Hs2_i) #b #H2
+lapply (diag_spec β€¦ Hcode_i) #H3
+@(absurd1 (lang i βŒ©i,bβŒͺ))
+@(iff_trans β€¦ (H3 βŒ©i,bβŒͺ)) 
+@(iff_trans β€¦ (equiv_diag β€¦)) >fst_pair 
+%[* #_ // |#H6 % // ]
+qed.
+
+(******************************************************************************)
+
+definition to_Some β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
+
+definition deopt β‰ Ξ»n. match n with 
+  [ None β‡’ 1
+  | Some n β‡’ n].
+  
+definition opt_comp β‰ Ξ»f,g:nat β†’ option nat. Ξ»x.
+  match g x with 
+  [ None β‡’ None ?
+  | Some y β‡’ f y ].   
+
+(* axiom CFU: βˆ€h,g,s. CF s (to_Some h)  β†’ CF s (to_Some (of_size βˆ˜ g)) β†’ 
+  CF (Slow s) (Ξ»x.U (h x) (g x)). *)
+  
+axiom sU2: nat β†’ nat β†’ nat.
+axiom sU: nat β†’ nat β†’ nat β†’ nat.
+
+(* axiom CFU: CF sU (Ξ»x.U (fst x) (snd x)). *)
+
+axiom CFU_new: βˆ€h,g,f,s. 
+  CF s (to_Some h)  β†’ CF s (to_Some g) β†’ CF s (to_Some f) β†’ 
+  O s (Ξ»x. sU (size_f h x) (size_f g x) (size_f f x)) β†’ 
+  CF s (Ξ»x.U (h x) (g x) (|f x|)).
+    
+lemma CFU: βˆ€h,g,f,s1,s2,s3. 
+  CF s1 (to_Some h)  β†’ CF s2 (to_Some g) β†’ CF s3 (to_Some f) β†’ 
+  CF (Ξ»x. s1 x + s2 x + s3 x + sU (size_f h x) (size_f g x) (size_f f x)) 
+    (Ξ»x.U (h x) (g x) (|f x|)).
+#h #g #f #s1 #s2 #s3 #Hh #Hg #Hf @CFU_new
+  [@(monotonic_CF β€¦ Hh) @O_plus_l @O_plus_l @O_plus_l //
+  |@(monotonic_CF β€¦ Hg) @O_plus_l @O_plus_l @O_plus_r //
+  |@(monotonic_CF β€¦ Hf) @O_plus_l @O_plus_r //
+  |@O_plus_r //
+  ]
+qed.
+    
+axiom monotonic_sU: βˆ€a1,a2,b1,b2,c1,c2. a1 β‰€ a2 β†’ b1 β‰€ b2 β†’ c1 β‰€c2 β†’
+  sU a1 b1 c1 β‰€ sU a2 b2 c2.
+
+axiom superlinear_sU: βˆ€i,x,r. r β‰€ sU i x r.
+
+definition sU_space β‰ Ξ»i,x,r.i+x+r.
+definition sU_time β‰ Ξ»i,x,r.i+x+(i^2)*r*(log 2 r).
+
+(*
+axiom CF_comp: βˆ€f,g,s1, s2. CF s1 f β†’ CF s2 g β†’ 
+  CF (Ξ»x.s2 x + s1 (size (deopt (g x)))) (opt_comp f g).
+
+(* axiom CF_comp: βˆ€f,g,s1, s2. CF s1 f β†’ CF s2 g β†’ 
+  CF (s1 βˆ˜ (Ξ»x. size (deopt (g x)))) (opt_comp f g). *)
+  
+axiom CF_comp_strong: βˆ€f,g,s1,s2. CF s1 f β†’ CF s2 g β†’ 
+  CF (s1 βˆ˜ s2) (opt_comp f g). *)
+
+definition IF β‰ Ξ»b,f,g:nat β†’option nat. Ξ»x.
+  match b x with 
+  [None β‡’ None ?
+  |Some n β‡’ if (eqb n 0) then f x else g x].
+  
+axiom IF_CF_new: βˆ€b,f,g,s. CF s b β†’ CF s f β†’ CF s g β†’ CF s (IF b f g).
+
+lemma IF_CF: βˆ€b,f,g,sb,sf,sg. CF sb b β†’ CF sf f β†’ CF sg g β†’ 
+  CF (Ξ»n. sb n + sf n + sg n) (IF b f g).
+#b #f #g #sb #sf #sg #Hb #Hf #Hg @IF_CF_new
+  [@(monotonic_CF β€¦ Hb) @O_plus_l @O_plus_l //
+  |@(monotonic_CF β€¦ Hf) @O_plus_l @O_plus_r //
+  |@(monotonic_CF β€¦ Hg) @O_plus_r //
+  ]
+qed.
+
+lemma diag_cf_def : βˆ€s.βˆ€i. 
+  diag_cf s i =  
+    IF (Ξ»i.U (fst i) i (|of_size (s (|i|))|)) (Ξ»i.Some ? 1) (Ξ»i.Some ? 0) i.
+#s #i normalize >size_of_size // qed. 
+
+(* and now ... *)
+axiom CF_pair: βˆ€f,g,s. CF s (Ξ»x.Some ? (f x)) β†’ CF s (Ξ»x.Some ? (g x)) β†’ 
+  CF s (Ξ»x.Some ? (pair (f x) (g x))).
+
+axiom CF_fst: βˆ€f,s. CF s (Ξ»x.Some ? (f x)) β†’ CF s (Ξ»x.Some ? (fst (f x))).
+
+definition minimal β‰ Ξ»s. CF s (Ξ»n. Some ? n) βˆ§ βˆ€c. CF s (Ξ»n. Some ? c).
+
+
+(*
+axiom le_snd: βˆ€n. |snd n| β‰€ |n|.
+axiom daemon: βˆ€P:Prop.P. *)
+
+definition constructible β‰ Ξ»s. CF s (Ξ»x.Some ? (of_size (s (|x|)))).
+
+lemma diag_s: βˆ€s. minimal s β†’ constructible s β†’ 
+  CF (Ξ»x.sU x x (s x)) (diag_cf s).
+#s * #Hs_id #Hs_c #Hs_constr 
+cut (O (Ξ»x:β„•.sU x x (s x)) s) [%{1} %{0} #n //]
+#O_sU_s @ext_CF [2: #n @sym_eq @diag_cf_def | skip]
+@IF_CF_new [2,3:@(monotonic_CF β€¦ (Hs_c ?)) // ] 
+@CFU_new
+  [@CF_fst @(monotonic_CF β€¦ Hs_id) //
+  |@(monotonic_CF β€¦ Hs_id) //
+  |@(monotonic_CF β€¦ Hs_constr) //
+  |%{1} %{0} #n #_ >commutative_times <times_n_1
+   @monotonic_sU // >size_f_size >size_of_size //
+  ]
+qed. 
+
+(*
+lemma diag_s: βˆ€s. minimal s β†’ constructible s β†’ 
+  CF (Ξ»x.s x + sU x x (s x)) (diag_cf s).
+#s * #Hs_id #Hs_c #Hs_constr 
+@ext_CF [2: #n @sym_eq @diag_cf_def | skip]
+@IF_CF_new [2,3:@(monotonic_CF β€¦ (Hs_c ?)) @O_plus_l //]
+@CFU_new
+  [@CF_fst @(monotonic_CF β€¦ Hs_id) @O_plus_l //
+  |@(monotonic_CF β€¦ Hs_id) @O_plus_l //
+  |@(monotonic_CF β€¦ Hs_constr) @O_plus_l //
+  |@O_plus_r %{1} %{0} #n #_ >commutative_times <times_n_1
+   @monotonic_sU // >size_f_size >size_of_size //
+  ]
+qed. *)
+
+(* proof with old axioms
+lemma diag_s: βˆ€s. minimal s β†’ constructible s β†’ 
+  CF (Ξ»x.s x + sU x x (s x)) (diag_cf s).
+#s * #Hs_id #Hs_c #Hs_constr 
+@ext_CF [2: #n @sym_eq @diag_cf_def | skip]
+@(monotonic_CF ???? (IF_CF (Ξ»i:β„•.U (pair (fst i) i) (|of_size (s (|i|))|))
+   β€¦ (Ξ»i.s i + s i + s i + (sU (size_f fst i) (size_f (Ξ»i.i) i) (size_f (Ξ»i.of_size (s (|i|))) i))) β€¦ (Hs_c 1) (Hs_c 0) β€¦ ))
+  [2: @CFU [@CF_fst // | // |@Hs_constr]
+  |@(O_ext2 (Ξ»n:β„•.s n+sU (size_f fst n) n (s n) + (s n+s n+s n+s n))) 
+    [2: #i >size_f_size >size_of_size >size_f_id //] 
+   @O_absorbr 
+    [%{1} %{0} #n #_ >commutative_times <times_n_1 @le_plus //
+     @monotonic_sU // 
+    |@O_plus_l @(O_plus β€¦ (O_refl s)) @(O_plus β€¦ (O_refl s)) 
+     @(O_plus β€¦ (O_refl s)) //
+  ]
+qed.
+*)
+
+(*************************** The hierachy theorem *****************************)
+
+(*
+theorem hierarchy_theorem_right: βˆ€s1,s2:natβ†’nat. 
+  O s1 idN β†’ constructible s1 β†’
+    not_O s2 s1 β†’ Β¬ CF s1 βŠ† CF s2.
+#s1 #s2 #Hs1 #monos1 #H % #H1 
+@(absurd β€¦ (CF s2 (diag_cf s1)))
+  [@H1 @diag_s // |@(diag1_not_s1 β€¦ H)]
+qed.
+*)
+
+theorem hierarchy_theorem_left: βˆ€s1,s2:natβ†’nat.
+   O(s1) βŠ† O(s2) β†’ CF s1 βŠ† CF s2.
+#s1 #s2 #HO #f * #i * #Hcode * #c * #a #Hs1_i %{i} % //
+cases (sub_O_to_O β€¦ HO) -HO #c1 * #b #Hs1s2 
+%{(c*c1)} %{(max a b)} #x #lemax 
+cases (Hs1_i x ?) [2: @(le_maxl β€¦lemax)]
+#y #Hy %{y} @(monotonic_U β€¦ Hy) >associative_times
+@le_times // @Hs1s2 @(le_maxr β€¦ lemax)
+qed.
+
diff --git a/matita/matita/broken_lib/reverse_complexity/speed_clean.ma b/matita/matita/broken_lib/reverse_complexity/speed_clean.ma
new file mode 100644 (file)
index 0000000..bfd3d34
--- /dev/null
@@ -0,0 +1,1068 @@
+include "basics/types.ma".
+include "arithmetics/minimization.ma".
+include "arithmetics/bigops.ma".
+include "arithmetics/sigma_pi.ma".
+include "arithmetics/bounded_quantifiers.ma".
+include "reverse_complexity/big_O.ma".
+include "basics/core_notation/napart_2.ma".
+
+(************************* notation for minimization *****************************)
+notation "ΞΌ_{ ident i < n } p" 
+  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
+
+notation "ΞΌ_{ ident i β‰€ n } p" 
+  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
+  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
+  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
+  
+(************************************ MAX *************************************)
+notation "Max_{ ident i < n | p } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident i < n } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident j βˆˆ [a,b[ } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+  
+notation "Max_{ ident j βˆˆ [a,b[ | p } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+
+lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
+#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
+  [cases (true_or_false (leb b c )) #lebc >lebc normalize
+    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
+    |>leab //
+    ]
+  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
+   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
+   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
+  ]
+qed.
+
+lemma Max0 : βˆ€n. max 0 n = n.
+// qed.
+
+lemma Max0r : βˆ€n. max n 0 = n.
+#n >commutative_max //
+qed.
+
+definition MaxA β‰ 
+  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
+
+definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
+
+lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
+  f a β‰€  Max_{i < n | p i}(f i).
+#f #p #n #a #ltan #pa 
+>(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
+qed.
+
+lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
+  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
+#f #p #n #m #a #lema #ltan #pa 
+>(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
+  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
+  |<plus_minus_m_m //
+  |/2 by monotonic_lt_minus_l/
+  ]
+qed.
+
+lemma Max_le: βˆ€f,p,n,b. 
+  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
+#f #p #n elim n #b #H // 
+#b0 #H1 cases (true_or_false (p b)) #Hb
+  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
+  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
+  ]
+qed.
+
+(********************************** pairing ***********************************)
+axiom pair: nat β†’ nat β†’ nat.
+axiom fst : nat β†’ nat.
+axiom snd : nat β†’ nat.
+
+interpretation "abstract pair" 'pair f g = (pair f g). 
+
+axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
+axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
+axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
+
+axiom le_fst : βˆ€p. fst p β‰€ p.
+axiom le_snd : βˆ€p. snd p β‰€ p.
+axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
+
+(************************************* U **************************************)
+axiom U: nat β†’ nat β†’nat β†’ option nat. 
+
+axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
+  U i x n = Some ? y β†’ U i x m = Some ? y.
+  
+lemma unique_U: βˆ€i,x,n,m,yn,ym.
+  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
+#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
+  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
+  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
+   >Hn #HS destruct (HS) //
+  ]
+qed.
+
+definition code_for β‰ Ξ»f,i.βˆ€x.
+  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
+
+definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
+
+notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
+
+lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
+#i #x #n normalize cases (U i x n)
+  [%2 % * #y #H destruct|#y %1 %{y} //]
+qed.
+  
+lemma monotonic_terminate: βˆ€i,x,n,m.
+  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
+#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
+qed.
+
+definition termb β‰ Ξ»i,x,t. 
+  match U i x t with [None β‡’ false |Some y β‡’ true].
+
+lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
+#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
+qed.    
+
+lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
+#i #x #t * #y #H normalize >H // 
+qed.    
+
+definition out β‰ Ξ»i,x,r. 
+  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
+
+definition bool_to_nat: bool β†’ nat β‰ 
+  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
+
+coercion bool_to_nat. 
+
+definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
+
+lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
+#i #x #r #y % normalize
+  [cases (U i x r) normalize 
+    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
+     #H1 destruct
+    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
+     #H1 //
+    ]
+  |#H >H //]
+qed.
+  
+lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
+#i #x #r % normalize
+  [cases (U i x r) normalize //
+   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
+   #H1 destruct
+  |#H >H //]
+qed.
+
+lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
+#i #x #r normalize cases (U i x r) normalize >fst_pair //
+qed.
+
+lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
+#i #x #r normalize cases (U i x r) normalize >snd_pair //
+qed.
+
+(********************************* the speedup ********************************)
+
+definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
+
+lemma min_input_def : βˆ€h,i,x. 
+  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
+// qed.
+
+lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
+#h #i #x #lexi >min_input_def 
+cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
+qed. 
+
+lemma min_input_to_terminate: βˆ€h,i,x. 
+  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
+#h #i #x #Hminx
+cases (decidable_le (S i) x) #Hix
+  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
+    [@termb_true_to_term //
+    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
+     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
+     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
+     #Habs @False_ind /2/
+    ]
+  |@False_ind >min_input_i in Hminx; 
+    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+  ]
+qed.
+
+lemma min_input_to_lt: βˆ€h,i,x. 
+  min_input h i x = x β†’ i < x.
+#h #i #x #Hminx cases (decidable_le (S i) x) // 
+#ltxi @False_ind >min_input_i in Hminx; 
+  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+qed.
+
+lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
+  min_input h i x = x β†’ min_input h i x1 = x.
+#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
+  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
+  |@(min_input_to_lt β€¦ Hminx)
+  |#j #H1 <Hminx @lt_min_to_false //
+  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
+   @(min_input_to_lt β€¦ Hminx)
+  ]
+qed.
+  
+definition g β‰ Ξ»h,u,x. 
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+  
+lemma g_def : βˆ€h,u,x. g h u x =
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+// qed.
+
+lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
+#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
+#eq0 >eq0 normalize // qed.
+
+lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
+  out i x (h (S i) x) < g h 0 x.
+#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
+qed.
+
+(*
+axiom ax1: βˆ€h,i.
+   (βˆƒy.i < y βˆ§ (termb i y (h (S i) y)=true)) βˆ¨ 
+    βˆ€y. i < y β†’ (termb i y (h (S i) y)=false).
+
+lemma eventually_0: βˆ€h,u.βˆƒnu.βˆ€x. nu < x β†’ 
+  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) = 0.
+#h #u elim u
+  [%{0} normalize //
+  |#u0 * #nu0 #Hind cases (ax1 h u0) 
+    [* #x0 * #leu0x0 #Hx0 %{(max nu0 x0)}
+     #x #Hx >bigop_Sfalse
+      [>(minus_n_O u0) @Hind @(le_to_lt_to_lt β€¦ Hx) /2 by le_maxl/
+      |@not_eq_to_eqb_false % #Hf @(absurd (x β‰€ x0)) 
+        [<Hf @true_to_le_min //
+        |@lt_to_not_le @(le_to_lt_to_lt β€¦ Hx) /2 by le_maxl/
+        ]
+      ]
+    |#H %{(max u0 nu0)} #x #Hx >bigop_Sfalse
+      [>(minus_n_O u0) @Hind @(le_to_lt_to_lt β€¦ Hx) @le_maxr //
+      |@not_eq_to_eqb_false >min_input_def
+       >(min_not_exists (Ξ»y.(termb (u0+0) y (h (S (u0+0)) y)))) 
+        [<plus_n_O <plus_n_Sm <plus_minus_m_m 
+          [% #H1 /2/ 
+          |@lt_to_le @(le_to_lt_to_lt β€¦ Hx) @le_maxl //
+          ]
+        |/2 by /
+        ]
+      ]
+    ]
+  ]
+qed.
+
+definition almost_equal β‰ Ξ»f,g:nat β†’ nat. βˆƒnu.βˆ€x. nu < x β†’ f x = g x.
+
+definition almost_equal1 β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
+
+interpretation "almost equal" 'napart f g = (almost_equal f g). 
+
+lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
+#h #u cases (eventually_0 h u) #nu #H %{(max u nu)} #x #Hx @(eq_f ?? S)
+>(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA)
+  [>H // @(le_to_lt_to_lt β€¦Hx) /2 by le_maxl/
+  |@lt_to_le @(le_to_lt_to_lt β€¦Hx) /2 by le_maxr/
+  |//
+  ]
+qed. *)
+
+lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
+#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
+  [#H %2 @H | #H %1 @H]  
+qed.
+
+definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
+interpretation "almost equal" 'napart f g = (almost_equal f g). 
+
+lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
+  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
+#h #u elim u
+  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
+  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
+   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
+    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
+      [2: #H %{x} % // <minus_n_O @H]
+     #Hneq0 (* if x is not enough we retry with nu=x *)
+     cases (Hind x) #x1 * #ltx1 
+     >bigop_Sfalse 
+      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
+      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
+        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
+      ]  
+    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
+    ]
+  ]
+qed.
+
+lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
+#h #u @(not_to_not β€¦ (eventually_cancelled h u))
+#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
+%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
+#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
+  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
+qed.
+
+(******************************** Condition 2 *********************************)
+definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
+  
+lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
+#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
+  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
+  |#y #leiy #lty @(lt_min_to_false ????? lty) //
+  ]
+qed.
+
+lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
+#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
+lapply (g_lt β€¦ Hminy)
+lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
+cases (H y) -H #ny #Hy 
+cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
+whd in match (out ???); >termy >Hr  
+#H @(absurd ? H) @le_to_not_lt @le_n
+qed.
+
+
+(********************** complexity ***********************)
+
+(* We assume operations have a minimal structural complexity MSC. 
+For instance, for time complexity, MSC is equal to the size of input.
+For space complexity, MSC is typically 0, since we only measure the
+space required in addition to dimension of the input. *)
+
+axiom MSC : nat β†’ nat.
+axiom MSC_le: βˆ€n. MSC n β‰€ n.
+axiom monotonic_MSC: monotonic ? le MSC.
+axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
+
+(* C s i means i is running in O(s) *)
+definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
+  U i x (c*(s x)) = Some ? y.
+
+(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
+definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
+lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
+#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
+  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
+qed.
+
+(* lemma ext_CF_total : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s (total f) β†’ CF s (total g).
+#f #g #s #Hext * #HO * #i * #Hcode #HC % // %{i} % [2:@HC]
+#x cases (Hcode x) #a #H %{a} #m #leam >(H m leam) normalize @eq_f @Hext
+qed. *)
+
+lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
+   @le_times // 
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
+   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
+  ]
+qed.
+
+lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [@(O_trans β€¦ H) //
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
+   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
+   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
+   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
+  ]
+qed.
+
+lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
+#s #f #c @O_to_CF @O_times_c 
+qed.
+
+(********************************* composition ********************************)
+axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
+  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
+  
+lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
+  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
+#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
+  [#n normalize @Heq | @(CF_comp β€¦ H) //]
+qed.
+
+(*
+lemma CF_comp1: βˆ€f,g,s. CF s (total g) β†’ CF s (total f) β†’ 
+  CF s (total (f βˆ˜ g)).
+#f #g #s #Hg #Hf @(timesc_CF β€¦ 2) @(monotonic_CF β€¦ (CF_comp β€¦ Hg Hf))
+*)
+
+(*
+axiom CF_comp_ext2: βˆ€f,g,h,sf,sh. CF sh (total g) β†’ CF sf (total f) β†’ 
+  (βˆ€x.f(g x) = h x) β†’ 
+  (βˆ€x. sf (g x) β‰€ sh x) β†’ CF sh (total h). 
+
+lemma main_MSC: βˆ€h,f. CF h f β†’ O h (Ξ»x.MSC (f x)). 
+axiom CF_S: CF MSC S.
+axiom CF_fst: CF MSC fst.
+axiom CF_snd: CF MSC snd.
+
+lemma CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
+#h #f #Hf @(CF_comp β€¦ Hf CF_S) @O_plus // @main_MSC //
+qed. 
+
+lemma CF_comp_fst: βˆ€h,f. CF h (total f) β†’ CF h (total (fst βˆ˜ f)).
+#h #f #Hf @(CF_comp β€¦ Hf CF_fst) @O_plus // @main_MSC //
+qed.
+
+lemma CF_comp_snd: βˆ€h,f. CF h (total f) β†’ CF h (total (snd βˆ˜ f)).
+#h #f #Hf @(CF_comp β€¦ Hf CF_snd) @O_plus // @main_MSC //
+qed. *)
+
+definition id β‰ Ξ»x:nat.x.
+
+axiom CF_id: CF MSC id.
+axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
+axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
+axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
+axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
+
+lemma CF_fst: CF MSC fst.
+@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
+qed.
+
+lemma CF_snd: CF MSC snd.
+@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
+qed.
+
+(************************************** eqb ***********************************)
+(* definition btotal β‰ 
+  Ξ»f.Ξ»x:nat. match f x with [true β‡’ Some ? 0 |false β‡’ Some ? 1]. *)
+  
+axiom CF_eqb: βˆ€h,f,g.
+  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
+
+(* 
+axiom eqb_compl2: βˆ€h,f,g.
+  CF2 h (total2 f) β†’ CF2 h (total2 g) β†’ 
+    CF2 h (btotal2 (Ξ»x1,x2.eqb (f x1 x2) (g x1 x2))).
+
+axiom eqb_min_input_compl:βˆ€h,x. 
+   CF (Ξ»i.βˆ‘_{y βˆˆ [S i,S x[ }(h i y))
+   (btotal (Ξ»i.eqb (min_input h i x) x)). *)
+(*********************************** maximum **********************************) 
+
+axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
+  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
+  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
+
+(******************************** minimization ********************************) 
+
+axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
+  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
+  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
+
+(****************************** constructibility ******************************)
+definition constructible β‰ Ξ»s. CF s s.
+
+lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
+  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
+#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
+qed.
+
+lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
+  constructible s1 β†’ constructible s2.
+#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
+qed. 
+
+(********************************* simulation *********************************)
+
+axiom sU : nat β†’ nat. 
+
+axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
+  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
+
+lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
+snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
+#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
+#b1 * #c1 #eqy >eqy -eqy
+cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
+#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
+>fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
+qed.
+  
+axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+
+definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
+
+axiom CF_U : CF sU pU_unary.
+
+definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
+definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
+
+lemma CF_termb: CF sU termb_unary. 
+@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
+qed.
+
+lemma CF_out: CF sU out_unary. 
+@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
+qed.
+
+(*
+lemma CF_termb_comp: βˆ€f.CF (sU βˆ˜ f) (termb_unary βˆ˜ f).
+#f @(CF_comp β€¦ CF_termb) *)
+  
+(******************** complexity of g ********************)
+
+definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
+definition auxg β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
+    (out i (snd ux) (h (S i) (snd ux))).
+
+lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
+#h #s #H1 @(CF_compS ? (auxg h) H1) 
+qed.
+
+definition aux1g β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
+    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
+
+lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
+#h #x @same_bigop
+  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
+qed.
+
+lemma compl_g2 : βˆ€h,s1,s2,s. 
+  CF s1
+    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
+  CF s2
+    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
+  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
+  CF s (auxg h).
+#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
+  [#n whd in βŠ’ (??%%); @eq_aux]
+@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
+@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+qed.  
+
+lemma compl_g3 : βˆ€h,s.
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
+  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
+#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
+@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
+qed.
+
+definition min_input_aux β‰ Ξ»h,p.
+  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
+    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
+    
+lemma min_input_eq : βˆ€h,p. 
+    min_input_aux h p  =
+    min_input h (fst p) (snd (snd p)).
+#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
+whd in βŠ’ (??%%); >fst_pair >snd_pair //
+qed.
+
+definition termb_aux β‰ Ξ»h.
+  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
+
+(*
+lemma termb_aux : βˆ€h,p.
+  (Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x))) 
+    βŒ©fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ =
+  termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)) .
+#h #p normalize >fst_pair >snd_pair >fst_pair >snd_pair // 
+qed. *)
+
+lemma compl_g4 : βˆ€h,s1,s.
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
+ [#n whd in βŠ’ (??%%); @min_input_eq]
+@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
+  [@CF_compS @CF_fst 
+  |@CF_comp_snd @CF_snd
+  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+(* @(ext_CF (btotal (termb_aux h)))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_compb β€¦ CF_termb) *)
+qed.
+
+(************************* a couple of technical lemmas ***********************)
+lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
+#a elim a // #n #Hind * 
+  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
+qed.
+
+lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
+  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut (b = pred (S b - a + a)) 
+    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
+   generalize in match (S b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] @le_plus 
+      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
+  ]
+qed.
+
+lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
+  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] #Hm 
+     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
+     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
+  ]
+qed. 
+
+lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
+O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
+  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
+qed.
+
+lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
+O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
+qed.
+
+lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
+[@O_plus_l // |@O_plus_r @coroll @Hmono]
+qed.
+
+(*
+axiom compl_g6: βˆ€h.
+  (* constructible (Ξ»x. h (fst x) (snd x)) β†’ *)
+  (CF (Ξ»x. max (MSC x) (sU βŒ©fst (snd x),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ))
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
+*)
+
+lemma compl_g6: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
+#h #hconstr @(ext_CF (termb_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
+  [@CF_comp_pair
+    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
+    |@CF_comp_pair
+      [@(monotonic_CF β€¦ CF_fst) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus
+    [@O_plus
+      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         >distributive_times_plus @le_plus [//]
+         cases (surj_pair b) #c * #d #eqb >eqb
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
+        ]     
+      |@le_to_O #n @sU_le
+      ] 
+    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
+  ]
+qed.
+             
+(* definition faux1 β‰ Ξ»h.
+  (Ξ»x.MSC x + (snd (snd x)-fst x)*(Ξ»x.sU βŒ©fst (snd x),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
+  
+(* complexity of min_input *)
+lemma compl_g7: βˆ€h. 
+  (βˆ€x.MSC x≀h (S (fst (snd x))) (fst x)) β†’
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©fst x,〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hle #hcostr #hmono @(monotonic_CF β€¦ (faux1 h))
+  [#n normalize >fst_pair >snd_pair //]
+@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
+>fst_pair >snd_pair @monotonic_sU // @hmono @lexy
+qed.*)
+
+definition big : nat β†’nat β‰ Ξ»x. 
+  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
+
+lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
+#a #b normalize >fst_pair >snd_pair // qed.
+
+lemma le_big : βˆ€x. x β‰€ big x. 
+#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
+[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
+qed.
+
+definition faux2 β‰ Ξ»h.
+  (Ξ»x.MSC x + (snd (snd x)-fst x)*
+    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
+(* proviamo con x *)
+lemma compl_g7: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
+  [#n normalize >fst_pair >snd_pair //]
+@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
+>fst_pair >snd_pair @monotonic_sU // @hmono @lexy
+qed.
+
+(* proviamo con x *)
+lemma compl_g71: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
+@le_plus [@monotonic_MSC //]
+cases (decidable_le (fst x) (snd(snd x))) 
+  [#Hle @le_times // @monotonic_sU  
+  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
+  ]
+qed.
+
+(*
+axiom compl_g8: βˆ€h.
+  CF (Ξ»x. sU βŒ©fst x,〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))). *)
+
+definition out_aux β‰ Ξ»h.
+  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
+
+lemma compl_g8: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
+    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
+#h #hconstr @(ext_CF (out_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
+  [@CF_comp_pair
+    [@(monotonic_CF β€¦ CF_fst) #x //
+    |@CF_comp_pair
+      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus 
+    [@O_plus 
+      [@le_to_O #n @sU_le 
+      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
+        ]
+      ]
+    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
+  ]
+qed.
+
+(*
+lemma compl_g81: βˆ€h.
+  (βˆ€x.MSC x≀h (S (fst x)) (snd(snd x))) β†’
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))).
+#h #hle #hconstr @(monotonic_CF ???? (compl_g8 h hle hconstr)) #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦ )) 
+qed. *)
+
+(* axiom daemon : False. *)
+
+lemma compl_g9 : βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
+      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
+   (auxg h).
+#h #hconstr #hmono #hantimono 
+@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
+@O_plus 
+  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
+    [// | @monotonic_MSC // ]]
+@(O_trans β€¦ (coroll2 ??))
+  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
+   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
+   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
+   @le_plus
+    [@le_plus [>big_def >big_def >maxa >maxb //]
+     @le_times 
+      [/2 by monotonic_le_minus_r/ 
+      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
+      ]
+    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
+    ] 
+  |@le_to_O #n >fst_pair >snd_pair
+   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
+   >associative_plus >distributive_times_plus
+   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
+  ]
+qed.
+
+definition sg β‰ Ξ»h,x.
+  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
+
+lemma sg_def : βˆ€h,a,b. 
+  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
+   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
+#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
+qed. 
+
+lemma compl_g11 : βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (sg h) (unary_g h).
+#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
+qed. 
+
+(**************************** closing the argument ****************************)
+
+let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
+  match d with 
+  [ O β‡’ c (* MSC βŒ©βŒ©b,bβŒͺ,〈b,bβŒͺβŒͺ *)
+  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
+     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
+
+lemma h_of_aux_O: βˆ€r,c,b.
+  h_of_aux r c O b  = c.
+// qed.
+
+lemma h_of_aux_S : βˆ€r,c,d,b. 
+  h_of_aux r c (S d) b = 
+    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
+      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
+// qed.
+
+definition h_of β‰ Ξ»r,p. 
+  let m β‰ max (fst p) (snd p) in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
+
+lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
+  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
+#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
+qed.
+
+lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
+  let m β‰ max a b in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
+#r #a #b normalize >fst_pair >snd_pair //
+qed.
+  
+lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
+  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
+#r #Hr #monor #d #d1 lapply d -d elim d1 
+  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
+   >h_of_aux_O >h_of_aux_O  //
+  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
+    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
+     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
+     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
+     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
+    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
+     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
+     @le_plus [@le_times //] 
+      [@monotonic_MSC @le_pair @le_pair //
+      |@le_times [//] @monotonic_sU 
+        [@le_pair // |// |@monor @Hind //]
+      ]
+    ]
+  ]
+qed.
+
+lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
+#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
+cut (max i a β‰€ max i b)
+  [@to_max 
+    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
+#Hmax @(mono_h_of_aux r Hr Hmono) 
+  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
+qed.
+
+axiom h_of_constr : βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  constructible (h_of r).
+
+lemma speed_compl: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
+#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
+  [#x cases (surj_pair x) #a * #b #eqx >eqx 
+   >sg_def cases (decidable_le b a)
+    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
+     <plus_n_O <plus_n_O >h_of_def 
+     cut (max a b = a) 
+      [normalize cases (le_to_or_lt_eq β€¦ leba)
+        [#ltba >(lt_to_leb_false β€¦ ltba) % 
+        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
+     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
+     @monotonic_MSC @le_pair @le_pair //
+    |#ltab >h_of_def >h_of_def
+     cut (max a b = b) 
+      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
+     #Hmax >Hmax 
+     cut (max (S a) b = b) 
+      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
+     #Hmax1 >Hmax1
+     cut (βˆƒd.b - a = S d) 
+       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
+     * #d #eqd >eqd  
+     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
+     cut (b - S d = a) 
+       [@plus_to_minus >commutative_plus @minus_to_plus 
+         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
+     normalize //
+    ]
+  |#n #a #b #leab #lebn >h_of_def >h_of_def
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
+   cut (max b n = n) 
+    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
+   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
+  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
+  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
+    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
+   @(h_of_constr r Hr Hmono Hconstr)
+  ]
+qed.
+
+(* 
+lemma unary_g_def : βˆ€h,i,x. g h i x = unary_g h βŒ©i,xβŒͺ.
+#h #i #x whd in βŠ’ (???%); >fst_pair >snd_pair %
+qed.  *)
+
+(* smn *)
+axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
+
+lemma speed_compl_i: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
+#r #Hr #Hmono #Hconstr #i 
+@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
+  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
+@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
+qed.
+
+theorem pseudo_speedup: 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
+(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
+#r #Hr #Hmono #Hconstr
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
+  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
+  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
+ ]
+qed.
+
+theorem pseudo_speedup': 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
+  (* Β¬ O (r βˆ˜ sg) sf. *)
+  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
+#r #Hr #Hmono #Hconstr 
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha
+  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
+  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
+  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
+ ]
+qed.
+  
diff --git a/matita/matita/broken_lib/reverse_complexity/speed_def.ma b/matita/matita/broken_lib/reverse_complexity/speed_def.ma
new file mode 100644 (file)
index 0000000..9812cfb
--- /dev/null
@@ -0,0 +1,922 @@
+include "basics/types.ma".
+include "arithmetics/minimization.ma".
+include "arithmetics/bigops.ma".
+include "arithmetics/sigma_pi.ma".
+include "arithmetics/bounded_quantifiers.ma".
+include "reverse_complexity/big_O.ma".
+include "basics/core_notation/napart_2.ma".
+
+(************************* notation for minimization *****************************)
+notation "ΞΌ_{ ident i < n } p" 
+  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
+
+notation "ΞΌ_{ ident i β‰€ n } p" 
+  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
+  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
+  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
+  
+(************************************ MAX *************************************)
+notation "Max_{ ident i < n | p } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident i < n } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident j βˆˆ [a,b[ } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+  
+notation "Max_{ ident j βˆˆ [a,b[ | p } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+
+lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
+#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
+  [cases (true_or_false (leb b c )) #lebc >lebc normalize
+    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
+    |>leab //
+    ]
+  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
+   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
+   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
+  ]
+qed.
+
+lemma Max0 : βˆ€n. max 0 n = n.
+// qed.
+
+lemma Max0r : βˆ€n. max n 0 = n.
+#n >commutative_max //
+qed.
+
+definition MaxA β‰ 
+  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
+
+definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
+
+lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
+  f a β‰€  Max_{i < n | p i}(f i).
+#f #p #n #a #ltan #pa 
+>(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
+qed.
+
+lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
+  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
+#f #p #n #m #a #lema #ltan #pa 
+>(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
+  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
+  |<plus_minus_m_m //
+  |/2 by monotonic_lt_minus_l/
+  ]
+qed.
+
+lemma Max_le: βˆ€f,p,n,b. 
+  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
+#f #p #n elim n #b #H // 
+#b0 #H1 cases (true_or_false (p b)) #Hb
+  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
+  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
+  ]
+qed.
+
+(********************************** pairing ***********************************)
+axiom pair: nat β†’ nat β†’ nat.
+axiom fst : nat β†’ nat.
+axiom snd : nat β†’ nat.
+
+interpretation "abstract pair" 'pair f g = (pair f g). 
+
+axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
+axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
+axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
+
+axiom le_fst : βˆ€p. fst p β‰€ p.
+axiom le_snd : βˆ€p. snd p β‰€ p.
+axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
+
+(************************************* U **************************************)
+axiom U: nat β†’ nat β†’nat β†’ option nat. 
+
+axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
+  U i x n = Some ? y β†’ U i x m = Some ? y.
+  
+lemma unique_U: βˆ€i,x,n,m,yn,ym.
+  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
+#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
+  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
+  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
+   >Hn #HS destruct (HS) //
+  ]
+qed.
+
+definition code_for β‰ Ξ»f,i.βˆ€x.
+  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
+
+definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
+
+notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
+
+lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
+#i #x #n normalize cases (U i x n)
+  [%2 % * #y #H destruct|#y %1 %{y} //]
+qed.
+  
+lemma monotonic_terminate: βˆ€i,x,n,m.
+  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
+#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
+qed.
+
+definition termb β‰ Ξ»i,x,t. 
+  match U i x t with [None β‡’ false |Some y β‡’ true].
+
+lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
+#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
+qed.    
+
+lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
+#i #x #t * #y #H normalize >H // 
+qed.    
+
+definition out β‰ Ξ»i,x,r. 
+  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
+
+definition bool_to_nat: bool β†’ nat β‰ 
+  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
+
+coercion bool_to_nat. 
+
+definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
+
+lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
+#i #x #r #y % normalize
+  [cases (U i x r) normalize 
+    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
+     #H1 destruct
+    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
+     #H1 //
+    ]
+  |#H >H //]
+qed.
+  
+lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
+#i #x #r % normalize
+  [cases (U i x r) normalize //
+   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
+   #H1 destruct
+  |#H >H //]
+qed.
+
+lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
+#i #x #r normalize cases (U i x r) normalize >fst_pair //
+qed.
+
+lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
+#i #x #r normalize cases (U i x r) normalize >snd_pair //
+qed.
+
+(********************************* the speedup ********************************)
+
+definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
+
+lemma min_input_def : βˆ€h,i,x. 
+  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
+// qed.
+
+lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
+#h #i #x #lexi >min_input_def 
+cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
+qed. 
+
+lemma min_input_to_terminate: βˆ€h,i,x. 
+  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
+#h #i #x #Hminx
+cases (decidable_le (S i) x) #Hix
+  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
+    [@termb_true_to_term //
+    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
+     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
+     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
+     #Habs @False_ind /2/
+    ]
+  |@False_ind >min_input_i in Hminx; 
+    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+  ]
+qed.
+
+lemma min_input_to_lt: βˆ€h,i,x. 
+  min_input h i x = x β†’ i < x.
+#h #i #x #Hminx cases (decidable_le (S i) x) // 
+#ltxi @False_ind >min_input_i in Hminx; 
+  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+qed.
+
+lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
+  min_input h i x = x β†’ min_input h i x1 = x.
+#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
+  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
+  |@(min_input_to_lt β€¦ Hminx)
+  |#j #H1 <Hminx @lt_min_to_false //
+  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
+   @(min_input_to_lt β€¦ Hminx)
+  ]
+qed.
+  
+definition g β‰ Ξ»h,u,x. 
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+  
+lemma g_def : βˆ€h,u,x. g h u x =
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+// qed.
+
+lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
+#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
+#eq0 >eq0 normalize // qed.
+
+lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
+  out i x (h (S i) x) < g h 0 x.
+#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
+qed.
+
+lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
+#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
+  [#H %2 @H | #H %1 @H]  
+qed.
+
+definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
+interpretation "almost equal" 'napart f g = (almost_equal f g). 
+
+lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
+  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
+#h #u elim u
+  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
+  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
+   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
+    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
+      [2: #H %{x} % // <minus_n_O @H]
+     #Hneq0 (* if x is not enough we retry with nu=x *)
+     cases (Hind x) #x1 * #ltx1 
+     >bigop_Sfalse 
+      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
+      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
+        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
+      ]  
+    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
+    ]
+  ]
+qed.
+
+lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
+#h #u @(not_to_not β€¦ (eventually_cancelled h u))
+#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
+%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
+#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
+  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
+qed.
+
+(******************************** Condition 2 *********************************)
+definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
+  
+lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
+#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
+  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
+  |#y #leiy #lty @(lt_min_to_false ????? lty) //
+  ]
+qed.
+
+lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
+#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
+lapply (g_lt β€¦ Hminy)
+lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
+cases (H y) -H #ny #Hy 
+cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
+whd in match (out ???); >termy >Hr  
+#H @(absurd ? H) @le_to_not_lt @le_n
+qed.
+
+
+(********************************* complexity *********************************)
+
+(* We assume operations have a minimal structural complexity MSC. 
+For instance, for time complexity, MSC is equal to the size of input.
+For space complexity, MSC is typically 0, since we only measure the
+space required in addition to dimension of the input. *)
+
+axiom MSC : nat β†’ nat.
+axiom MSC_le: βˆ€n. MSC n β‰€ n.
+axiom monotonic_MSC: monotonic ? le MSC.
+axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
+
+(* C s i means i is running in O(s) *)
+definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
+  U i x (c*(s x)) = Some ? y.
+
+(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
+definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
+lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
+#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
+  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
+qed.
+
+lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
+   @le_times // 
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
+   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
+  ]
+qed.
+
+lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [@(O_trans β€¦ H) //
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
+   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
+   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
+   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
+  ]
+qed.
+
+lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
+#s #f #c @O_to_CF @O_times_c 
+qed.
+
+(********************************* composition ********************************)
+axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
+  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
+  
+lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
+  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
+#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
+  [#n normalize @Heq | @(CF_comp β€¦ H) //]
+qed.
+
+
+(**************************** primitive operations*****************************)
+
+definition id β‰ Ξ»x:nat.x.
+
+axiom CF_id: CF MSC id.
+axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
+axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
+axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
+axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
+
+lemma CF_fst: CF MSC fst.
+@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
+qed.
+
+lemma CF_snd: CF MSC snd.
+@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
+qed.
+
+(************************************** eqb ***********************************)
+  
+axiom CF_eqb: βˆ€h,f,g.
+  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
+
+(*********************************** maximum **********************************) 
+
+axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
+  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
+  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
+
+(******************************** minimization ********************************) 
+
+axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
+  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
+  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
+  
+(************************************* smn ************************************)
+axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
+
+(****************************** constructibility ******************************)
+definition constructible β‰ Ξ»s. CF s s.
+
+lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
+  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
+#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
+qed.
+
+lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
+  constructible s1 β†’ constructible s2.
+#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
+qed. 
+
+(********************************* simulation *********************************)
+
+axiom sU : nat β†’ nat. 
+
+axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
+  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
+
+lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
+snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
+#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
+#b1 * #c1 #eqy >eqy -eqy
+cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
+#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
+>fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
+qed.
+  
+axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+
+definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
+
+axiom CF_U : CF sU pU_unary.
+
+definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
+definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
+
+lemma CF_termb: CF sU termb_unary. 
+@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
+qed.
+
+lemma CF_out: CF sU out_unary. 
+@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
+qed.
+
+
+(******************** complexity of g ********************)
+
+definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
+definition auxg β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
+    (out i (snd ux) (h (S i) (snd ux))).
+
+lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
+#h #s #H1 @(CF_compS ? (auxg h) H1) 
+qed.
+
+definition aux1g β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
+    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
+
+lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
+#h #x @same_bigop
+  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
+qed.
+
+lemma compl_g2 : βˆ€h,s1,s2,s. 
+  CF s1
+    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
+  CF s2
+    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
+  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
+  CF s (auxg h).
+#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
+  [#n whd in βŠ’ (??%%); @eq_aux]
+@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
+@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+qed.  
+
+lemma compl_g3 : βˆ€h,s.
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
+  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
+#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
+@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
+qed.
+
+definition min_input_aux β‰ Ξ»h,p.
+  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
+    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
+    
+lemma min_input_eq : βˆ€h,p. 
+    min_input_aux h p  =
+    min_input h (fst p) (snd (snd p)).
+#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
+whd in βŠ’ (??%%); >fst_pair >snd_pair //
+qed.
+
+definition termb_aux β‰ Ξ»h.
+  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
+
+lemma compl_g4 : βˆ€h,s1,s.
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
+ [#n whd in βŠ’ (??%%); @min_input_eq]
+@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
+  [@CF_compS @CF_fst 
+  |@CF_comp_snd @CF_snd
+  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+qed.
+
+(************************* a couple of technical lemmas ***********************)
+lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
+#a elim a // #n #Hind * 
+  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
+qed.
+
+lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
+  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut (b = pred (S b - a + a)) 
+    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
+   generalize in match (S b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] @le_plus 
+      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
+  ]
+qed.
+
+lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
+  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] #Hm 
+     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
+     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
+  ]
+qed. 
+
+lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
+O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
+  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
+qed.
+
+lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
+O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
+qed.
+
+(**************************** end of technical lemmas *************************)
+
+lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
+[@O_plus_l // |@O_plus_r @coroll @Hmono]
+qed.
+
+lemma compl_g6: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
+#h #hconstr @(ext_CF (termb_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
+  [@CF_comp_pair
+    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
+    |@CF_comp_pair
+      [@(monotonic_CF β€¦ CF_fst) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus
+    [@O_plus
+      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         >distributive_times_plus @le_plus [//]
+         cases (surj_pair b) #c * #d #eqb >eqb
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
+        ]     
+      |@le_to_O #n @sU_le
+      ] 
+    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
+  ]
+qed.
+
+definition big : nat β†’nat β‰ Ξ»x. 
+  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
+
+lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
+#a #b normalize >fst_pair >snd_pair // qed.
+
+lemma le_big : βˆ€x. x β‰€ big x. 
+#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
+[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
+qed.
+
+definition faux2 β‰ Ξ»h.
+  (Ξ»x.MSC x + (snd (snd x)-fst x)*
+    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
+lemma compl_g7: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
+  [#n normalize >fst_pair >snd_pair //]
+@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
+>fst_pair >snd_pair @monotonic_sU // @hmono @lexy
+qed.
+
+lemma compl_g71: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
+@le_plus [@monotonic_MSC //]
+cases (decidable_le (fst x) (snd(snd x))) 
+  [#Hle @le_times // @monotonic_sU  
+  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
+  ]
+qed.
+
+definition out_aux β‰ Ξ»h.
+  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
+
+lemma compl_g8: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
+    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
+#h #hconstr @(ext_CF (out_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
+  [@CF_comp_pair
+    [@(monotonic_CF β€¦ CF_fst) #x //
+    |@CF_comp_pair
+      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus 
+    [@O_plus 
+      [@le_to_O #n @sU_le 
+      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
+        ]
+      ]
+    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
+  ]
+qed.
+
+lemma compl_g9 : βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
+      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
+   (auxg h).
+#h #hconstr #hmono #hantimono 
+@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
+@O_plus 
+  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
+    [// | @monotonic_MSC // ]]
+@(O_trans β€¦ (coroll2 ??))
+  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
+   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
+   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
+   @le_plus
+    [@le_plus [>big_def >big_def >maxa >maxb //]
+     @le_times 
+      [/2 by monotonic_le_minus_r/ 
+      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
+      ]
+    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
+    ] 
+  |@le_to_O #n >fst_pair >snd_pair
+   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
+   >associative_plus >distributive_times_plus
+   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
+  ]
+qed.
+
+definition sg β‰ Ξ»h,x.
+  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
+
+lemma sg_def : βˆ€h,a,b. 
+  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
+   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
+#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
+qed. 
+
+lemma compl_g11 : βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (sg h) (unary_g h).
+#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
+qed. 
+
+(**************************** closing the argument ****************************)
+
+let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
+  match d with 
+  [ O β‡’ c 
+  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
+     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
+
+lemma h_of_aux_O: βˆ€r,c,b.
+  h_of_aux r c O b  = c.
+// qed.
+
+lemma h_of_aux_S : βˆ€r,c,d,b. 
+  h_of_aux r c (S d) b = 
+    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
+      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
+// qed.
+
+definition h_of β‰ Ξ»r,p. 
+  let m β‰ max (fst p) (snd p) in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
+
+lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
+  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
+#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
+qed.
+
+lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
+  let m β‰ max a b in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
+#r #a #b normalize >fst_pair >snd_pair //
+qed.
+  
+lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
+  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
+#r #Hr #monor #d #d1 lapply d -d elim d1 
+  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
+   >h_of_aux_O >h_of_aux_O  //
+  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
+    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
+     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
+     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
+     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
+    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
+     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
+     @le_plus [@le_times //] 
+      [@monotonic_MSC @le_pair @le_pair //
+      |@le_times [//] @monotonic_sU 
+        [@le_pair // |// |@monor @Hind //]
+      ]
+    ]
+  ]
+qed.
+
+lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
+#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
+cut (max i a β‰€ max i b)
+  [@to_max 
+    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
+#Hmax @(mono_h_of_aux r Hr Hmono) 
+  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
+qed.
+
+axiom h_of_constr : βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  constructible (h_of r).
+
+lemma speed_compl: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
+#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
+  [#x cases (surj_pair x) #a * #b #eqx >eqx 
+   >sg_def cases (decidable_le b a)
+    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
+     <plus_n_O <plus_n_O >h_of_def 
+     cut (max a b = a) 
+      [normalize cases (le_to_or_lt_eq β€¦ leba)
+        [#ltba >(lt_to_leb_false β€¦ ltba) % 
+        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
+     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
+     @monotonic_MSC @le_pair @le_pair //
+    |#ltab >h_of_def >h_of_def
+     cut (max a b = b) 
+      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
+     #Hmax >Hmax 
+     cut (max (S a) b = b) 
+      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
+     #Hmax1 >Hmax1
+     cut (βˆƒd.b - a = S d) 
+       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
+     * #d #eqd >eqd  
+     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
+     cut (b - S d = a) 
+       [@plus_to_minus >commutative_plus @minus_to_plus 
+         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
+     normalize //
+    ]
+  |#n #a #b #leab #lebn >h_of_def >h_of_def
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
+   cut (max b n = n) 
+    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
+   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
+  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
+  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
+    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
+   @(h_of_constr r Hr Hmono Hconstr)
+  ]
+qed.
+
+lemma speed_compl_i: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
+#r #Hr #Hmono #Hconstr #i 
+@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
+  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
+@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
+qed.
+
+(**************************** the speedup theorem *****************************)
+theorem pseudo_speedup: 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
+(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
+#r #Hr #Hmono #Hconstr
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
+  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
+  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
+ ]
+qed.
+
+theorem pseudo_speedup': 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
+  (* Β¬ O (r βˆ˜ sg) sf. *)
+  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
+#r #Hr #Hmono #Hconstr 
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha
+  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
+  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
+  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
+ ]
+qed.
+  
diff --git a/matita/matita/broken_lib/reverse_complexity/speed_new.ma b/matita/matita/broken_lib/reverse_complexity/speed_new.ma
new file mode 100644 (file)
index 0000000..9812cfb
--- /dev/null
@@ -0,0 +1,922 @@
+include "basics/types.ma".
+include "arithmetics/minimization.ma".
+include "arithmetics/bigops.ma".
+include "arithmetics/sigma_pi.ma".
+include "arithmetics/bounded_quantifiers.ma".
+include "reverse_complexity/big_O.ma".
+include "basics/core_notation/napart_2.ma".
+
+(************************* notation for minimization *****************************)
+notation "ΞΌ_{ ident i < n } p" 
+  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
+
+notation "ΞΌ_{ ident i β‰€ n } p" 
+  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
+  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
+  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
+  
+(************************************ MAX *************************************)
+notation "Max_{ ident i < n | p } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident i < n } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident j βˆˆ [a,b[ } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+  
+notation "Max_{ ident j βˆˆ [a,b[ | p } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+
+lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
+#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
+  [cases (true_or_false (leb b c )) #lebc >lebc normalize
+    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
+    |>leab //
+    ]
+  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
+   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
+   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
+  ]
+qed.
+
+lemma Max0 : βˆ€n. max 0 n = n.
+// qed.
+
+lemma Max0r : βˆ€n. max n 0 = n.
+#n >commutative_max //
+qed.
+
+definition MaxA β‰ 
+  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
+
+definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
+
+lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
+  f a β‰€  Max_{i < n | p i}(f i).
+#f #p #n #a #ltan #pa 
+>(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
+qed.
+
+lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
+  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
+#f #p #n #m #a #lema #ltan #pa 
+>(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
+  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
+  |<plus_minus_m_m //
+  |/2 by monotonic_lt_minus_l/
+  ]
+qed.
+
+lemma Max_le: βˆ€f,p,n,b. 
+  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
+#f #p #n elim n #b #H // 
+#b0 #H1 cases (true_or_false (p b)) #Hb
+  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
+  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
+  ]
+qed.
+
+(********************************** pairing ***********************************)
+axiom pair: nat β†’ nat β†’ nat.
+axiom fst : nat β†’ nat.
+axiom snd : nat β†’ nat.
+
+interpretation "abstract pair" 'pair f g = (pair f g). 
+
+axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
+axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
+axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
+
+axiom le_fst : βˆ€p. fst p β‰€ p.
+axiom le_snd : βˆ€p. snd p β‰€ p.
+axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
+
+(************************************* U **************************************)
+axiom U: nat β†’ nat β†’nat β†’ option nat. 
+
+axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
+  U i x n = Some ? y β†’ U i x m = Some ? y.
+  
+lemma unique_U: βˆ€i,x,n,m,yn,ym.
+  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
+#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
+  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
+  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
+   >Hn #HS destruct (HS) //
+  ]
+qed.
+
+definition code_for β‰ Ξ»f,i.βˆ€x.
+  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
+
+definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
+
+notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
+
+lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
+#i #x #n normalize cases (U i x n)
+  [%2 % * #y #H destruct|#y %1 %{y} //]
+qed.
+  
+lemma monotonic_terminate: βˆ€i,x,n,m.
+  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
+#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
+qed.
+
+definition termb β‰ Ξ»i,x,t. 
+  match U i x t with [None β‡’ false |Some y β‡’ true].
+
+lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
+#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
+qed.    
+
+lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
+#i #x #t * #y #H normalize >H // 
+qed.    
+
+definition out β‰ Ξ»i,x,r. 
+  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
+
+definition bool_to_nat: bool β†’ nat β‰ 
+  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
+
+coercion bool_to_nat. 
+
+definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
+
+lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
+#i #x #r #y % normalize
+  [cases (U i x r) normalize 
+    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
+     #H1 destruct
+    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
+     #H1 //
+    ]
+  |#H >H //]
+qed.
+  
+lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
+#i #x #r % normalize
+  [cases (U i x r) normalize //
+   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
+   #H1 destruct
+  |#H >H //]
+qed.
+
+lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
+#i #x #r normalize cases (U i x r) normalize >fst_pair //
+qed.
+
+lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
+#i #x #r normalize cases (U i x r) normalize >snd_pair //
+qed.
+
+(********************************* the speedup ********************************)
+
+definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
+
+lemma min_input_def : βˆ€h,i,x. 
+  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
+// qed.
+
+lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
+#h #i #x #lexi >min_input_def 
+cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
+qed. 
+
+lemma min_input_to_terminate: βˆ€h,i,x. 
+  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
+#h #i #x #Hminx
+cases (decidable_le (S i) x) #Hix
+  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
+    [@termb_true_to_term //
+    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
+     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
+     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
+     #Habs @False_ind /2/
+    ]
+  |@False_ind >min_input_i in Hminx; 
+    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+  ]
+qed.
+
+lemma min_input_to_lt: βˆ€h,i,x. 
+  min_input h i x = x β†’ i < x.
+#h #i #x #Hminx cases (decidable_le (S i) x) // 
+#ltxi @False_ind >min_input_i in Hminx; 
+  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+qed.
+
+lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
+  min_input h i x = x β†’ min_input h i x1 = x.
+#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
+  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
+  |@(min_input_to_lt β€¦ Hminx)
+  |#j #H1 <Hminx @lt_min_to_false //
+  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
+   @(min_input_to_lt β€¦ Hminx)
+  ]
+qed.
+  
+definition g β‰ Ξ»h,u,x. 
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+  
+lemma g_def : βˆ€h,u,x. g h u x =
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+// qed.
+
+lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
+#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
+#eq0 >eq0 normalize // qed.
+
+lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
+  out i x (h (S i) x) < g h 0 x.
+#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
+qed.
+
+lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
+#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
+  [#H %2 @H | #H %1 @H]  
+qed.
+
+definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
+interpretation "almost equal" 'napart f g = (almost_equal f g). 
+
+lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
+  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
+#h #u elim u
+  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
+  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
+   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
+    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
+      [2: #H %{x} % // <minus_n_O @H]
+     #Hneq0 (* if x is not enough we retry with nu=x *)
+     cases (Hind x) #x1 * #ltx1 
+     >bigop_Sfalse 
+      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
+      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
+        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
+      ]  
+    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
+    ]
+  ]
+qed.
+
+lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
+#h #u @(not_to_not β€¦ (eventually_cancelled h u))
+#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
+%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
+#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
+  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
+qed.
+
+(******************************** Condition 2 *********************************)
+definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
+  
+lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
+#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
+  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
+  |#y #leiy #lty @(lt_min_to_false ????? lty) //
+  ]
+qed.
+
+lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
+#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
+lapply (g_lt β€¦ Hminy)
+lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
+cases (H y) -H #ny #Hy 
+cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
+whd in match (out ???); >termy >Hr  
+#H @(absurd ? H) @le_to_not_lt @le_n
+qed.
+
+
+(********************************* complexity *********************************)
+
+(* We assume operations have a minimal structural complexity MSC. 
+For instance, for time complexity, MSC is equal to the size of input.
+For space complexity, MSC is typically 0, since we only measure the
+space required in addition to dimension of the input. *)
+
+axiom MSC : nat β†’ nat.
+axiom MSC_le: βˆ€n. MSC n β‰€ n.
+axiom monotonic_MSC: monotonic ? le MSC.
+axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
+
+(* C s i means i is running in O(s) *)
+definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
+  U i x (c*(s x)) = Some ? y.
+
+(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
+definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
+lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
+#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
+  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
+qed.
+
+lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
+   @le_times // 
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
+   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
+  ]
+qed.
+
+lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [@(O_trans β€¦ H) //
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
+   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
+   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
+   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
+  ]
+qed.
+
+lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
+#s #f #c @O_to_CF @O_times_c 
+qed.
+
+(********************************* composition ********************************)
+axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
+  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
+  
+lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
+  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
+#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
+  [#n normalize @Heq | @(CF_comp β€¦ H) //]
+qed.
+
+
+(**************************** primitive operations*****************************)
+
+definition id β‰ Ξ»x:nat.x.
+
+axiom CF_id: CF MSC id.
+axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
+axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
+axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
+axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
+
+lemma CF_fst: CF MSC fst.
+@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
+qed.
+
+lemma CF_snd: CF MSC snd.
+@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
+qed.
+
+(************************************** eqb ***********************************)
+  
+axiom CF_eqb: βˆ€h,f,g.
+  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
+
+(*********************************** maximum **********************************) 
+
+axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
+  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
+  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
+
+(******************************** minimization ********************************) 
+
+axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
+  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
+  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
+  
+(************************************* smn ************************************)
+axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
+
+(****************************** constructibility ******************************)
+definition constructible β‰ Ξ»s. CF s s.
+
+lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
+  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
+#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
+qed.
+
+lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
+  constructible s1 β†’ constructible s2.
+#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
+qed. 
+
+(********************************* simulation *********************************)
+
+axiom sU : nat β†’ nat. 
+
+axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
+  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
+
+lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
+snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
+#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
+#b1 * #c1 #eqy >eqy -eqy
+cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
+#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
+>fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
+qed.
+  
+axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+
+definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
+
+axiom CF_U : CF sU pU_unary.
+
+definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
+definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
+
+lemma CF_termb: CF sU termb_unary. 
+@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
+qed.
+
+lemma CF_out: CF sU out_unary. 
+@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
+qed.
+
+
+(******************** complexity of g ********************)
+
+definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
+definition auxg β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
+    (out i (snd ux) (h (S i) (snd ux))).
+
+lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
+#h #s #H1 @(CF_compS ? (auxg h) H1) 
+qed.
+
+definition aux1g β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
+    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
+
+lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
+#h #x @same_bigop
+  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
+qed.
+
+lemma compl_g2 : βˆ€h,s1,s2,s. 
+  CF s1
+    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
+  CF s2
+    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
+  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
+  CF s (auxg h).
+#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
+  [#n whd in βŠ’ (??%%); @eq_aux]
+@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
+@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+qed.  
+
+lemma compl_g3 : βˆ€h,s.
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
+  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
+#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
+@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
+qed.
+
+definition min_input_aux β‰ Ξ»h,p.
+  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
+    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
+    
+lemma min_input_eq : βˆ€h,p. 
+    min_input_aux h p  =
+    min_input h (fst p) (snd (snd p)).
+#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
+whd in βŠ’ (??%%); >fst_pair >snd_pair //
+qed.
+
+definition termb_aux β‰ Ξ»h.
+  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
+
+lemma compl_g4 : βˆ€h,s1,s.
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
+ [#n whd in βŠ’ (??%%); @min_input_eq]
+@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
+  [@CF_compS @CF_fst 
+  |@CF_comp_snd @CF_snd
+  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+qed.
+
+(************************* a couple of technical lemmas ***********************)
+lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
+#a elim a // #n #Hind * 
+  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
+qed.
+
+lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
+  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut (b = pred (S b - a + a)) 
+    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
+   generalize in match (S b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] @le_plus 
+      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
+  ]
+qed.
+
+lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
+  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] #Hm 
+     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
+     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
+  ]
+qed. 
+
+lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
+O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
+  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
+qed.
+
+lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
+O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
+qed.
+
+(**************************** end of technical lemmas *************************)
+
+lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
+[@O_plus_l // |@O_plus_r @coroll @Hmono]
+qed.
+
+lemma compl_g6: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
+#h #hconstr @(ext_CF (termb_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
+  [@CF_comp_pair
+    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
+    |@CF_comp_pair
+      [@(monotonic_CF β€¦ CF_fst) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus
+    [@O_plus
+      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         >distributive_times_plus @le_plus [//]
+         cases (surj_pair b) #c * #d #eqb >eqb
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
+        ]     
+      |@le_to_O #n @sU_le
+      ] 
+    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
+  ]
+qed.
+
+definition big : nat β†’nat β‰ Ξ»x. 
+  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
+
+lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
+#a #b normalize >fst_pair >snd_pair // qed.
+
+lemma le_big : βˆ€x. x β‰€ big x. 
+#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
+[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
+qed.
+
+definition faux2 β‰ Ξ»h.
+  (Ξ»x.MSC x + (snd (snd x)-fst x)*
+    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
+lemma compl_g7: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
+  [#n normalize >fst_pair >snd_pair //]
+@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
+>fst_pair >snd_pair @monotonic_sU // @hmono @lexy
+qed.
+
+lemma compl_g71: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
+@le_plus [@monotonic_MSC //]
+cases (decidable_le (fst x) (snd(snd x))) 
+  [#Hle @le_times // @monotonic_sU  
+  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
+  ]
+qed.
+
+definition out_aux β‰ Ξ»h.
+  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
+
+lemma compl_g8: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
+    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
+#h #hconstr @(ext_CF (out_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
+  [@CF_comp_pair
+    [@(monotonic_CF β€¦ CF_fst) #x //
+    |@CF_comp_pair
+      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus 
+    [@O_plus 
+      [@le_to_O #n @sU_le 
+      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
+        ]
+      ]
+    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
+  ]
+qed.
+
+lemma compl_g9 : βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
+      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
+   (auxg h).
+#h #hconstr #hmono #hantimono 
+@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
+@O_plus 
+  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
+    [// | @monotonic_MSC // ]]
+@(O_trans β€¦ (coroll2 ??))
+  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
+   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
+   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
+   @le_plus
+    [@le_plus [>big_def >big_def >maxa >maxb //]
+     @le_times 
+      [/2 by monotonic_le_minus_r/ 
+      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
+      ]
+    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
+    ] 
+  |@le_to_O #n >fst_pair >snd_pair
+   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
+   >associative_plus >distributive_times_plus
+   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
+  ]
+qed.
+
+definition sg β‰ Ξ»h,x.
+  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
+
+lemma sg_def : βˆ€h,a,b. 
+  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
+   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
+#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
+qed. 
+
+lemma compl_g11 : βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (sg h) (unary_g h).
+#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
+qed. 
+
+(**************************** closing the argument ****************************)
+
+let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
+  match d with 
+  [ O β‡’ c 
+  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
+     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
+
+lemma h_of_aux_O: βˆ€r,c,b.
+  h_of_aux r c O b  = c.
+// qed.
+
+lemma h_of_aux_S : βˆ€r,c,d,b. 
+  h_of_aux r c (S d) b = 
+    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
+      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
+// qed.
+
+definition h_of β‰ Ξ»r,p. 
+  let m β‰ max (fst p) (snd p) in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
+
+lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
+  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
+#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
+qed.
+
+lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
+  let m β‰ max a b in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
+#r #a #b normalize >fst_pair >snd_pair //
+qed.
+  
+lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
+  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
+#r #Hr #monor #d #d1 lapply d -d elim d1 
+  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
+   >h_of_aux_O >h_of_aux_O  //
+  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
+    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
+     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
+     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
+     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
+    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
+     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
+     @le_plus [@le_times //] 
+      [@monotonic_MSC @le_pair @le_pair //
+      |@le_times [//] @monotonic_sU 
+        [@le_pair // |// |@monor @Hind //]
+      ]
+    ]
+  ]
+qed.
+
+lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
+#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
+cut (max i a β‰€ max i b)
+  [@to_max 
+    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
+#Hmax @(mono_h_of_aux r Hr Hmono) 
+  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
+qed.
+
+axiom h_of_constr : βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  constructible (h_of r).
+
+lemma speed_compl: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
+#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
+  [#x cases (surj_pair x) #a * #b #eqx >eqx 
+   >sg_def cases (decidable_le b a)
+    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
+     <plus_n_O <plus_n_O >h_of_def 
+     cut (max a b = a) 
+      [normalize cases (le_to_or_lt_eq β€¦ leba)
+        [#ltba >(lt_to_leb_false β€¦ ltba) % 
+        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
+     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
+     @monotonic_MSC @le_pair @le_pair //
+    |#ltab >h_of_def >h_of_def
+     cut (max a b = b) 
+      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
+     #Hmax >Hmax 
+     cut (max (S a) b = b) 
+      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
+     #Hmax1 >Hmax1
+     cut (βˆƒd.b - a = S d) 
+       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
+     * #d #eqd >eqd  
+     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
+     cut (b - S d = a) 
+       [@plus_to_minus >commutative_plus @minus_to_plus 
+         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
+     normalize //
+    ]
+  |#n #a #b #leab #lebn >h_of_def >h_of_def
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
+   cut (max b n = n) 
+    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
+   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
+  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
+  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
+    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
+   @(h_of_constr r Hr Hmono Hconstr)
+  ]
+qed.
+
+lemma speed_compl_i: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
+#r #Hr #Hmono #Hconstr #i 
+@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
+  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
+@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
+qed.
+
+(**************************** the speedup theorem *****************************)
+theorem pseudo_speedup: 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
+(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
+#r #Hr #Hmono #Hconstr
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
+  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
+  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
+ ]
+qed.
+
+theorem pseudo_speedup': 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
+  (* Β¬ O (r βˆ˜ sg) sf. *)
+  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
+#r #Hr #Hmono #Hconstr 
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha
+  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
+  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
+  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
+ ]
+qed.
+  
diff --git a/matita/matita/broken_lib/reverse_complexity/toolkit.ma b/matita/matita/broken_lib/reverse_complexity/toolkit.ma
new file mode 100644 (file)
index 0000000..69fa352
--- /dev/null
@@ -0,0 +1,988 @@
+include "basics/types.ma".
+include "arithmetics/minimization.ma".
+include "arithmetics/bigops.ma".
+include "arithmetics/sigma_pi.ma".
+include "arithmetics/bounded_quantifiers.ma".
+include "reverse_complexity/big_O.ma".
+include "basics/core_notation/napart_2.ma".
+
+(************************* notation for minimization *****************************)
+notation "ΞΌ_{ ident i < n } p" 
+  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
+
+notation "ΞΌ_{ ident i β‰€ n } p" 
+  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
+  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
+  
+notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
+  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
+  
+(************************************ MAX *************************************)
+notation "Max_{ ident i < n | p } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident i < n } f"
+  with precedence 80
+for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
+
+notation "Max_{ ident j βˆˆ [a,b[ } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+  
+notation "Max_{ ident j βˆˆ [a,b[ | p } f"
+  with precedence 80
+for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
+  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
+
+lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
+#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
+  [cases (true_or_false (leb b c )) #lebc >lebc normalize
+    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
+    |>leab //
+    ]
+  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
+   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
+   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
+  ]
+qed.
+
+lemma Max0 : βˆ€n. max 0 n = n.
+// qed.
+
+lemma Max0r : βˆ€n. max n 0 = n.
+#n >commutative_max //
+qed.
+
+definition MaxA β‰ 
+  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
+
+definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
+
+lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
+  f a β‰€  Max_{i < n | p i}(f i).
+#f #p #n #a #ltan #pa 
+>(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
+qed.
+
+lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
+  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
+#f #p #n #m #a #lema #ltan #pa 
+>(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
+  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
+  |<plus_minus_m_m //
+  |/2 by monotonic_lt_minus_l/
+  ]
+qed.
+
+lemma Max_le: βˆ€f,p,n,b. 
+  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
+#f #p #n elim n #b #H // 
+#b0 #H1 cases (true_or_false (p b)) #Hb
+  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
+  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
+  ]
+qed.
+
+(********************************** pairing ***********************************)
+axiom pair: nat β†’ nat β†’ nat.
+axiom fst : nat β†’ nat.
+axiom snd : nat β†’ nat.
+
+interpretation "abstract pair" 'pair f g = (pair f g). 
+
+axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
+axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
+axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
+
+axiom le_fst : βˆ€p. fst p β‰€ p.
+axiom le_snd : βˆ€p. snd p β‰€ p.
+axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
+
+(************************************* U **************************************)
+axiom U: nat β†’ nat β†’nat β†’ option nat. 
+
+axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
+  U i x n = Some ? y β†’ U i x m = Some ? y.
+  
+lemma unique_U: βˆ€i,x,n,m,yn,ym.
+  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
+#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
+  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
+  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
+   >Hn #HS destruct (HS) //
+  ]
+qed.
+
+definition code_for β‰ Ξ»f,i.βˆ€x.
+  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
+
+definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
+
+notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
+
+lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
+#i #x #n normalize cases (U i x n)
+  [%2 % * #y #H destruct|#y %1 %{y} //]
+qed.
+  
+lemma monotonic_terminate: βˆ€i,x,n,m.
+  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
+#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
+qed.
+
+definition termb β‰ Ξ»i,x,t. 
+  match U i x t with [None β‡’ false |Some y β‡’ true].
+
+lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
+#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
+qed.    
+
+lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
+#i #x #t * #y #H normalize >H // 
+qed.    
+
+definition out β‰ Ξ»i,x,r. 
+  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
+
+definition bool_to_nat: bool β†’ nat β‰ 
+  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
+
+coercion bool_to_nat. 
+
+definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
+
+lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
+#i #x #r #y % normalize
+  [cases (U i x r) normalize 
+    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
+     #H1 destruct
+    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
+     #H1 //
+    ]
+  |#H >H //]
+qed.
+  
+lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
+#i #x #r % normalize
+  [cases (U i x r) normalize //
+   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
+   #H1 destruct
+  |#H >H //]
+qed.
+
+lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
+#i #x #r normalize cases (U i x r) normalize >fst_pair //
+qed.
+
+lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
+#i #x #r normalize cases (U i x r) normalize >snd_pair //
+qed.
+
+(********************************* the speedup ********************************)
+
+definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
+
+lemma min_input_def : βˆ€h,i,x. 
+  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
+// qed.
+
+lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
+#h #i #x #lexi >min_input_def 
+cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
+qed. 
+
+lemma min_input_to_terminate: βˆ€h,i,x. 
+  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
+#h #i #x #Hminx
+cases (decidable_le (S i) x) #Hix
+  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
+    [@termb_true_to_term //
+    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
+     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
+     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
+     #Habs @False_ind /2/
+    ]
+  |@False_ind >min_input_i in Hminx; 
+    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+  ]
+qed.
+
+lemma min_input_to_lt: βˆ€h,i,x. 
+  min_input h i x = x β†’ i < x.
+#h #i #x #Hminx cases (decidable_le (S i) x) // 
+#ltxi @False_ind >min_input_i in Hminx; 
+  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
+qed.
+
+lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
+  min_input h i x = x β†’ min_input h i x1 = x.
+#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
+  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
+  |@(min_input_to_lt β€¦ Hminx)
+  |#j #H1 <Hminx @lt_min_to_false //
+  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
+   @(min_input_to_lt β€¦ Hminx)
+  ]
+qed.
+  
+definition g β‰ Ξ»h,u,x. 
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+  
+lemma g_def : βˆ€h,u,x. g h u x =
+  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
+// qed.
+
+lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
+#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
+#eq0 >eq0 normalize // qed.
+
+lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
+  out i x (h (S i) x) < g h 0 x.
+#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
+qed.
+
+lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
+#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
+  [#H %2 @H | #H %1 @H]  
+qed.
+
+definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
+interpretation "almost equal" 'napart f g = (almost_equal f g). 
+
+lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
+  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
+#h #u elim u
+  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
+  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
+   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
+    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
+      [2: #H %{x} % // <minus_n_O @H]
+     #Hneq0 (* if x is not enough we retry with nu=x *)
+     cases (Hind x) #x1 * #ltx1 
+     >bigop_Sfalse 
+      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
+      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
+        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
+      ]  
+    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
+    ]
+  ]
+qed.
+
+lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
+#h #u @(not_to_not β€¦ (eventually_cancelled h u))
+#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
+%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
+#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
+  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
+qed.
+
+(******************************** Condition 2 *********************************)
+definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
+  
+lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
+#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
+  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
+  |#y #leiy #lty @(lt_min_to_false ????? lty) //
+  ]
+qed.
+
+lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
+#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
+lapply (g_lt β€¦ Hminy)
+lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
+cases (H y) -H #ny #Hy 
+cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
+whd in match (out ???); >termy >Hr  
+#H @(absurd ? H) @le_to_not_lt @le_n
+qed.
+
+
+(********************************* complexity *********************************)
+
+(* We assume operations have a minimal structural complexity MSC. 
+For instance, for time complexity, MSC is equal to the size of input.
+For space complexity, MSC is typically 0, since we only measure the
+space required in addition to dimension of the input. *)
+
+axiom MSC : nat β†’ nat.
+axiom MSC_le: βˆ€n. MSC n β‰€ n.
+axiom monotonic_MSC: monotonic ? le MSC.
+axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
+
+(* C s i means i is running in O(s) *)
+definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
+  U i x (c*(s x)) = Some ? y.
+
+(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
+definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
+lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
+#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
+  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
+qed.
+
+lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
+   @le_times // 
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
+   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
+  ]
+qed.
+
+lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
+#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
+  [@(O_trans β€¦ H) //
+  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
+   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
+   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
+   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
+  ]
+qed.
+
+lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
+#s #f #c @O_to_CF @O_times_c 
+qed.
+
+(********************************* composition ********************************)
+axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
+  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
+  
+lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
+  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
+#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
+  [#n normalize @Heq | @(CF_comp β€¦ H) //]
+qed.
+
+(* primitve recursion *)
+
+let rec prim_rec (k,h:nat β†’nat) n m on n β‰ 
+  match n with 
+  [ O β‡’ k m
+  | S a β‡’ h βŒ©a,〈prim_rec k h a m, mβŒͺβŒͺ].
+  
+lemma prim_rec_S: βˆ€k,h,n,m.
+  prim_rec k h (S n) m = h βŒ©n,〈prim_rec k h n m, mβŒͺβŒͺ.
+// qed.
+
+definition unary_pr β‰ Ξ»k,h,x. prim_rec k h (fst x) (snd x).
+
+let rec prim_rec_compl (k,h,sk,sh:nat β†’nat) n m on n β‰ 
+  match n with 
+  [ O β‡’ sk m
+  | S a β‡’ prim_rec_compl k h sk sh a m + sh (prim_rec k h a m)].
+  
+axiom CF_prim_rec: βˆ€k,h,sk,sh,sf. CF sk k β†’ CF sh h β†’ 
+  O sf (unary_pr sk (Ξ»x. fst (snd x) + sh βŒ©fst x,〈unary_pr k h βŒ©fst x,snd (snd x)βŒͺ,snd (snd x)βŒͺβŒͺ)) 
+   β†’ CF sf (unary_pr k h).
+
+(* falso ????
+lemma prim_rec_O: βˆ€k1,h1,k2,h2. O k1 k2 β†’ O h1 h2 β†’ 
+  O (unary_pr k1 h1) (unary_pr k2 h2).
+#k1 #h1 #k2 #h2 #HO1 #HO2 whd *)
+
+  
+(**************************** primitive operations*****************************)
+
+definition id β‰ Ξ»x:nat.x.
+
+axiom CF_id: CF MSC id.
+axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
+axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
+axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
+axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
+
+lemma CF_fst: CF MSC fst.
+@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
+qed.
+
+lemma CF_snd: CF MSC snd.
+@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
+qed.
+
+(************************************** eqb ***********************************)
+  
+axiom CF_eqb: βˆ€h,f,g.
+  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
+
+(*********************************** maximum **********************************) 
+
+axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
+  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
+  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
+
+(******************************** minimization ********************************) 
+
+axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
+  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
+  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
+  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
+  
+(************************************* smn ************************************)
+axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
+
+(****************************** constructibility ******************************)
+definition constructible β‰ Ξ»s. CF s s.
+
+lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
+  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
+#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
+qed.
+
+lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
+  constructible s1 β†’ constructible s2.
+#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
+qed.
+
+lemma constr_prim_rec: βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
+  (βˆ€n,r,m. 2 * r β‰€ s2 βŒ©n,〈r,mβŒͺβŒͺ) β†’ constructible (unary_pr s1 s2).
+#s1 #s2 #Hs1 #Hs2 #Hincr @(CF_prim_rec β€¦ Hs1 Hs2) whd %{2} %{0} 
+#x #_ lapply (surj_pair x) * #a * #b #eqx >eqx whd in match (unary_pr ???); 
+>fst_pair >snd_pair
+whd in match (unary_pr ???); >fst_pair >snd_pair elim a
+  [normalize //
+  |#n #Hind >prim_rec_S >fst_pair >snd_pair >fst_pair >snd_pair
+   >prim_rec_S @transitive_le [| @(monotonic_le_plus_l β€¦ Hind)]
+   @transitive_le [| @(monotonic_le_plus_l β€¦ (Hincr n ? b))] 
+   whd in match (unary_pr ???); >fst_pair >snd_pair //
+  ]
+qed.
+
+(********************************* simulation *********************************)
+
+axiom sU : nat β†’ nat. 
+
+axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
+  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
+
+lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
+snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
+#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
+#b1 * #c1 #eqy >eqy -eqy
+cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
+#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
+>fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
+qed.
+  
+axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
+
+definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
+
+axiom CF_U : CF sU pU_unary.
+
+definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
+definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
+
+lemma CF_termb: CF sU termb_unary. 
+@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
+qed.
+
+lemma CF_out: CF sU out_unary. 
+@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
+#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
+qed.
+
+
+(******************** complexity of g ********************)
+
+definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
+definition auxg β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
+    (out i (snd ux) (h (S i) (snd ux))).
+
+lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
+#h #s #H1 @(CF_compS ? (auxg h) H1) 
+qed.
+
+definition aux1g β‰ 
+  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
+    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
+
+lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
+#h #x @same_bigop
+  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
+qed.
+
+lemma compl_g2 : βˆ€h,s1,s2,s. 
+  CF s1
+    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
+  CF s2
+    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
+  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
+  CF s (auxg h).
+#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
+  [#n whd in βŠ’ (??%%); @eq_aux]
+@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
+@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+qed.  
+
+lemma compl_g3 : βˆ€h,s.
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
+  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
+#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
+@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
+qed.
+
+definition min_input_aux β‰ Ξ»h,p.
+  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
+    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
+    
+lemma min_input_eq : βˆ€h,p. 
+    min_input_aux h p  =
+    min_input h (fst p) (snd (snd p)).
+#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
+whd in βŠ’ (??%%); >fst_pair >snd_pair //
+qed.
+
+definition termb_aux β‰ Ξ»h.
+  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
+
+lemma compl_g4 : βˆ€h,s1,s.
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
+  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
+ [#n whd in βŠ’ (??%%); @min_input_eq]
+@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
+  [@CF_compS @CF_fst 
+  |@CF_comp_snd @CF_snd
+  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
+qed.
+
+(************************* a couple of technical lemmas ***********************)
+lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
+#a elim a // #n #Hind * 
+  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
+qed.
+
+lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
+  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut (b = pred (S b - a + a)) 
+    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
+   generalize in match (S b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] @le_plus 
+      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
+  ]
+qed.
+
+lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
+  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
+#h #a #b #H cases (decidable_le a b) 
+  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
+   #n elim n 
+    [//
+    |#m #Hind >bigop_Strue [2://] #Hm 
+     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
+     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
+    ]
+  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
+   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
+  ]
+qed. 
+
+lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
+O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
+  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
+qed.
+
+lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
+O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
+#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
+@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
+qed.
+
+(**************************** end of technical lemmas *************************)
+
+lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
+  (CF s1 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
+[@O_plus_l // |@O_plus_r @coroll @Hmono]
+qed.
+
+lemma compl_g6: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
+    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
+#h #hconstr @(ext_CF (termb_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
+  [@CF_comp_pair
+    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
+    |@CF_comp_pair
+      [@(monotonic_CF β€¦ CF_fst) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus
+    [@O_plus
+      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         >distributive_times_plus @le_plus [//]
+         cases (surj_pair b) #c * #d #eqb >eqb
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
+        ]     
+      |@le_to_O #n @sU_le
+      ] 
+    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
+  ]
+qed.
+
+definition big : nat β†’nat β‰ Ξ»x. 
+  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
+
+lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
+#a #b normalize >fst_pair >snd_pair // qed.
+
+lemma le_big : βˆ€x. x β‰€ big x. 
+#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
+[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
+qed.
+
+definition faux2 β‰ Ξ»h.
+  (Ξ»x.MSC x + (snd (snd x)-fst x)*
+    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
+lemma compl_g7: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
+  [#n normalize >fst_pair >snd_pair //]
+@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
+>fst_pair >snd_pair @monotonic_sU // @hmono @lexy
+qed.
+
+lemma compl_g71: βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
+    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
+#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
+@le_plus [@monotonic_MSC //]
+cases (decidable_le (fst x) (snd(snd x))) 
+  [#Hle @le_times // @monotonic_sU  
+  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
+  ]
+qed.
+
+definition out_aux β‰ Ξ»h.
+  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
+
+lemma compl_g8: βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
+    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
+#h #hconstr @(ext_CF (out_aux h))
+  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
+@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
+  [@CF_comp_pair
+    [@(monotonic_CF β€¦ CF_fst) #x //
+    |@CF_comp_pair
+      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
+      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
+        [#n normalize >fst_pair >snd_pair %]
+       @(CF_comp β€¦ MSC β€¦hconstr)
+        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
+        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
+        ]
+      ]
+    ]
+  |@O_plus 
+    [@O_plus 
+      [@le_to_O #n @sU_le 
+      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
+        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
+         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
+         whd in βŠ’ (??%); @le_plus 
+          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
+          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
+          ]
+        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
+        ]
+      ]
+    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
+  ]
+qed.
+
+lemma compl_g9 : βˆ€h. 
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
+      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
+   (auxg h).
+#h #hconstr #hmono #hantimono 
+@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
+@O_plus 
+  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
+    [// | @monotonic_MSC // ]]
+@(O_trans β€¦ (coroll2 ??))
+  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
+   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
+   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
+   @le_plus
+    [@le_plus [>big_def >big_def >maxa >maxb //]
+     @le_times 
+      [/2 by monotonic_le_minus_r/ 
+      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
+      ]
+    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
+    ] 
+  |@le_to_O #n >fst_pair >snd_pair
+   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
+   >associative_plus >distributive_times_plus
+   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
+  ]
+qed.
+
+definition sg β‰ Ξ»h,x.
+  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
+
+lemma sg_def : βˆ€h,a,b. 
+  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
+   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
+#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
+qed. 
+
+lemma compl_g11 : βˆ€h.
+  constructible (Ξ»x. h (fst x) (snd x)) β†’
+  (βˆ€n. monotonic ? le (h n)) β†’ 
+  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
+  CF (sg h) (unary_g h).
+#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
+qed. 
+
+(**************************** closing the argument ****************************)
+
+let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
+  match d with 
+  [ O β‡’ c 
+  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
+     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
+
+lemma h_of_aux_O: βˆ€r,c,b.
+  h_of_aux r c O b  = c.
+// qed.
+
+lemma h_of_aux_S : βˆ€r,c,d,b. 
+  h_of_aux r c (S d) b = 
+    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
+      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
+// qed.
+
+lemma h_of_aux_prim_rec : βˆ€r,c,n,b. h_of_aux r c n b =
+  prim_rec (Ξ»x.c) 
+   (Ξ»x.let d β‰ S(fst x) in 
+       let b β‰ snd (snd x) in
+       (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
+        d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (fst (snd x))βŒͺβŒͺ) n b.
+#r #c #n #b elim n
+  [>h_of_aux_O normalize //
+  |#n1 #Hind >h_of_aux_S >prim_rec_S >snd_pair >snd_pair >fst_pair 
+   >fst_pair <Hind //
+  ]
+qed.
+
+lemma h_of_aux_constr : 
+βˆ€r,c. constructible (Ξ»x.h_of_aux r c (fst x) (snd x)).
+#r #c 
+  @(ext_constr β€¦ 
+    (unary_pr (Ξ»x.c) 
+     (Ξ»x.let d β‰ S(fst x) in 
+       let b β‰ snd (snd x) in
+       (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
+        d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (fst (snd x))βŒͺβŒͺ)))
+  [#n @sym_eq whd in match (unary_pr ???); @h_of_aux_prim_rec
+  |@constr_prim_rec
+
+definition h_of β‰ Ξ»r,p. 
+  let m β‰ max (fst p) (snd p) in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
+
+lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
+  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
+#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
+qed.
+
+lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
+  let m β‰ max a b in 
+  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
+#r #a #b normalize >fst_pair >snd_pair //
+qed.
+  
+lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
+  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
+#r #Hr #monor #d #d1 lapply d -d elim d1 
+  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
+   >h_of_aux_O >h_of_aux_O  //
+  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
+    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
+     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
+     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
+     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
+    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
+     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
+     @le_plus [@le_times //] 
+      [@monotonic_MSC @le_pair @le_pair //
+      |@le_times [//] @monotonic_sU 
+        [@le_pair // |// |@monor @Hind //]
+      ]
+    ]
+  ]
+qed.
+
+lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
+  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
+#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
+cut (max i a β‰€ max i b)
+  [@to_max 
+    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
+#Hmax @(mono_h_of_aux r Hr Hmono) 
+  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
+qed.
+
+axiom h_of_constr : βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  constructible (h_of r).
+
+lemma speed_compl: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
+#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
+  [#x cases (surj_pair x) #a * #b #eqx >eqx 
+   >sg_def cases (decidable_le b a)
+    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
+     <plus_n_O <plus_n_O >h_of_def 
+     cut (max a b = a) 
+      [normalize cases (le_to_or_lt_eq β€¦ leba)
+        [#ltba >(lt_to_leb_false β€¦ ltba) % 
+        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
+     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
+     @monotonic_MSC @le_pair @le_pair //
+    |#ltab >h_of_def >h_of_def
+     cut (max a b = b) 
+      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
+     #Hmax >Hmax 
+     cut (max (S a) b = b) 
+      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
+     #Hmax1 >Hmax1
+     cut (βˆƒd.b - a = S d) 
+       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
+     * #d #eqd >eqd  
+     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
+     cut (b - S d = a) 
+       [@plus_to_minus >commutative_plus @minus_to_plus 
+         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
+     normalize //
+    ]
+  |#n #a #b #leab #lebn >h_of_def >h_of_def
+   cut (max a n = n) 
+    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
+   cut (max b n = n) 
+    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
+   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
+  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
+  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
+    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
+   @(h_of_constr r Hr Hmono Hconstr)
+  ]
+qed.
+
+lemma speed_compl_i: βˆ€r:nat β†’nat. 
+  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
+#r #Hr #Hmono #Hconstr #i 
+@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
+  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
+@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
+qed.
+
+(**************************** the speedup theorem *****************************)
+theorem pseudo_speedup: 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
+(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
+#r #Hr #Hmono #Hconstr
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
+  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
+  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
+ ]
+qed.
+
+theorem pseudo_speedup': 
+  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
+  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
+  (* Β¬ O (r βˆ˜ sg) sf. *)
+  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
+#r #Hr #Hmono #Hconstr 
+(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
+#Hcodei #HCi 
+(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
+%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
+(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
+%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
+lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
+%[%[@condition_1 |@Hg]
+ |cases Hg #H1 * #j * #Hcodej #HCj
+  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
+  cases HCi #m * #a #Ha
+  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
+  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
+  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
+  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
+  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
+ ]
+qed.
+  
diff --git a/matita/matita/broken_lib/turing/multi_to_mono/multi_to_mono.ma b/matita/matita/broken_lib/turing/multi_to_mono/multi_to_mono.ma
new file mode 100644 (file)
index 0000000..0e9bce5
--- /dev/null
@@ -0,0 +1,397 @@
+include "turing/auxiliary_machines1.ma".
+include "turing/multi_to_mono/shift_trace_machines.ma".
+
+(******************************************************************************)
+(* mtiL: complete move L for tape i. We reaching the left border of trace i,  *)
+(* add a blank if there is no more tape, then move the i-trace and finally    *)
+(* come back to the head position.                                            *)
+(******************************************************************************)
+
+(* we say that a tape is regular if for any trace after the first blank we
+  only have other blanks *)
+  
+definition all_blanks_in β‰ Ξ»sig,l.
+  βˆ€x. mem ? x l β†’ x = blank sig.  
+definition regular_i  β‰ Ξ»sig,n.Ξ»l:list (multi_sig sig n).Ξ»i.
+  all_blanks_in ? (after_blank ? (trace sig n i l)).
+
+definition regular_trace β‰ Ξ»sig,n,a.Ξ»ls,rs:list (multi_sig sig n).Ξ»i.
+  Or (And (regular_i sig n (a::ls) i) (regular_i sig n rs i))
+     (And (regular_i sig n ls i) (regular_i sig n (a::rs) i)).
+         
+axiom regular_tail: βˆ€sig,n,l,i.
+  regular_i sig n l i β†’ regular_i sig n (tail ? l) i.
+  
+axiom regular_extend: βˆ€sig,n,l,i.
+   regular_i sig n l i β†’ regular_i sig n (l@[all_blank sig n]) i.
+
+axiom all_blank_after_blank: βˆ€sig,n,l1,b,l2,i. 
+  nth i ? (vec β€¦ b) (blank ?) = blank ? β†’ 
+  regular_i sig n (l1@b::l2) i β†’ all_blanks_in ? (trace sig n i l2).
+   
+lemma regular_trace_extl:  βˆ€sig,n,a,ls,rs,i.
+  regular_trace sig n a ls rs i β†’ 
+    regular_trace sig n a (ls@[all_blank sig n]) rs i.
+#sig #n #a #ls #rs #i *
+  [* #H1 #H2 % % // @(regular_extend β€¦ H1)
+  |* #H1 #H2 %2 % // @(regular_extend β€¦ H1)
+  ]
+qed.
+
+lemma regular_cons_hd_rs: βˆ€sig,n.βˆ€a:multi_sig sig n.βˆ€ls,rs1,rs2,i.
+  regular_trace sig n a ls (rs1@rs2) i β†’ 
+    regular_trace sig n a ls (rs1@((hd ? rs2 (all_blank β€¦))::(tail ? rs2))) i.
+#sig #n #a #ls #rs1 #rs2 #i cases rs2 [2: #b #tl #H @H] 
+*[* #H1 >append_nil #H2 %1 % 
+   [@H1 | whd in match (hd ???); @(regular_extend β€¦ rs1) //]
+ |* #H1 >append_nil #H2 %2 % 
+   [@H1 | whd in match (hd ???); @(regular_extend β€¦ (a::rs1)) //]
+ ]
+qed.
+
+lemma eq_trace_to_regular : βˆ€sig,n.βˆ€a1,a2:multi_sig sig n.βˆ€ls1,ls2,rs1,rs2,i.
+   nth i ? (vec β€¦ a1) (blank ?) = nth i ? (vec β€¦ a2) (blank ?) β†’
+   trace sig n i ls1 = trace sig n i ls2 β†’ 
+   trace sig n i rs1 = trace sig n i rs2 β†’
+   regular_trace sig n a1 ls1 rs1 i β†’ 
+     regular_trace sig n a2 ls2 rs2 i.
+#sig #n #a1 #a2 #ls1 #ls2 #rs1 #rs2 #i #H1 #H2 #H3 #H4
+whd in match (regular_trace ??????); whd in match (regular_i ????);
+whd in match (regular_i ?? rs2 ?); whd in match (regular_i ?? ls2 ?);
+whd in match (regular_i ?? (a2::rs2) ?); whd in match (trace ????);
+<trace_def whd in match (trace ??? (a2::rs2)); <trace_def 
+<H1 <H2 <H3 @H4
+qed.
+
+(******************************* move_to_blank_L ******************************)
+(* we compose machines together to reduce the number of output cases, and 
+   improve semantics *)
+   
+definition move_to_blank_L β‰ Ξ»sig,n,i.
+  (move_until ? L (no_blank sig n i)) Β· extend ? (all_blank sig n).
+
+(*
+definition R_move_to_blank_L β‰ Ξ»sig,n,i,t1,t2.
+(current ? t1 = None ? β†’ 
+  t2 = midtape (multi_sig sig n) (left ? t1) (all_blank β€¦) (right ? t1)) βˆ§
+βˆ€ls,a,rs.t1 = midtape ? ls a rs β†’ 
+  ((no_blank sig n i a = false) βˆ§ t2 = t1) βˆ¨
+  (βˆƒb,ls1,ls2.
+    (no_blank sig n i b = false) βˆ§ 
+    (βˆ€j.j β‰€n β†’ to_blank_i ?? j (ls1@b::ls2) = to_blank_i ?? j ls) βˆ§
+    t2 = midtape ? ls2 b ((reverse ? (a::ls1))@rs)). 
+*)
+
+definition R_move_to_blank_L β‰ Ξ»sig,n,i,t1,t2.
+(current ? t1 = None ? β†’ 
+  t2 = midtape (multi_sig sig n) (left ? t1) (all_blank β€¦) (right ? t1)) βˆ§
+βˆ€ls,a,rs.
+  t1 = midtape (multi_sig sig n) ls a rs β†’ 
+  regular_i sig n (a::ls) i β†’
+  (βˆ€j. j β‰  i β†’ regular_trace β€¦ a ls rs j) β†’
+  (βˆƒb,ls1,ls2.
+    (regular_i sig n (ls1@b::ls2) i) βˆ§ 
+    (βˆ€j. j β‰  i β†’ regular_trace β€¦ 
+      (hd ? (ls1@b::ls2) (all_blank β€¦)) (tail ? (ls1@b::ls2)) rs j) βˆ§ 
+    (no_blank sig n i b = false) βˆ§ 
+    (hd (multi_sig sig n) (ls1@[b]) (all_blank β€¦) = a) βˆ§ (* not implied by the next fact *)
+    (βˆ€j.j β‰€n β†’ to_blank_i ?? j (ls1@b::ls2) = to_blank_i ?? j (a::ls)) βˆ§
+    t2 = midtape ? ls2 b ((reverse ? ls1)@rs)).
+
+theorem sem_move_to_blank_L: βˆ€sig,n,i. 
+  move_to_blank_L sig n i  βŠ¨ R_move_to_blank_L sig n i.
+#sig #n #i 
+@(sem_seq_app ?????? 
+  (ssem_move_until_L ? (no_blank sig n i)) (sem_extend ? (all_blank sig n)))
+#tin #tout * #t1 * * #Ht1a #Ht1b * #Ht2a #Ht2b %
+  [#Hcur >(Ht1a Hcur) in Ht2a; /2 by /
+  |#ls #a #rs #Htin #Hreg #Hreg2 -Ht1a cases (Ht1b β€¦ Htin)
+    [* #Hnb #Ht1 -Ht1b -Ht2a >Ht1 in Ht2b; >Htin #H 
+     %{a} %{[ ]} %{ls} 
+     %[%[%[%[%[@Hreg|@Hreg2]|@Hnb]|//]|//]|@H normalize % #H1 destruct (H1)]
+    |* 
+    [(* we find the blank *)
+     * #ls1 * #b * #ls2 * * * #H1 #H2 #H3 #Ht1
+     >Ht1 in Ht2b; #Hout -Ht1b
+     %{b} %{(a::ls1)} %{ls2} 
+     %[%[%[%[%[>H1 in Hreg; #H @H 
+              |#j #jneqi whd in match (hd ???); whd in match (tail ??);
+               <H1 @(Hreg2 j jneqi)]|@H2] |//]|>H1 //]
+      |@Hout normalize % normalize #H destruct (H)
+      ]
+    |* #b * #lss * * #H1 #H2 #Ht1 -Ht1b >Ht1 in Ht2a; 
+     whd in match (left ??); whd in match (right ??); #Hout
+     %{(all_blank β€¦)} %{(lss@[b])} %{[]}
+     %[%[%[%[%[<H2 @regular_extend // 
+              |<H2 #j #jneqi whd in match (hd ???); whd in match (tail ??); 
+               @regular_trace_extl @Hreg2 //]
+            |whd in match (no_blank ????); >blank_all_blank //]
+          |<H2 //]
+        |#j #lejn <H2 @sym_eq @to_blank_i_ext]
+      |>reverse_append >reverse_single @Hout normalize // 
+      ]
+    ]
+  ]
+qed.
+
+(******************************************************************************)
+   
+definition shift_i_L β‰ Ξ»sig,n,i.
+   ncombf_r (multi_sig β€¦) (shift_i sig n i) (all_blank sig n) Β·
+   mti sig n i Β· 
+   extend ? (all_blank sig n).
+   
+definition R_shift_i_L β‰ Ξ»sig,n,i,t1,t2.
+    (βˆ€a,ls,rs. 
+      t1 = midtape ? ls a rs  β†’ 
+      ((βˆƒrs1,b,rs2,a1,rss.
+        rs = rs1@b::rs2 βˆ§ 
+        nth i ? (vec β€¦ b) (blank ?) = (blank ?) βˆ§
+        (βˆ€x. mem ? x rs1 β†’ nth i ? (vec β€¦ x) (blank ?) β‰  (blank ?)) βˆ§
+        shift_l sig n i (a::rs1) (a1::rss) βˆ§
+        t2 = midtape (multi_sig sig n) ((reverse ? (a1::rss))@ls) b rs2) βˆ¨
+      (βˆƒb,rss. 
+        (βˆ€x. mem ? x rs β†’ nth i ? (vec β€¦ x) (blank ?) β‰  (blank ?)) βˆ§
+        shift_l sig n i (a::rs) (rss@[b]) βˆ§
+        t2 = midtape (multi_sig sig n) 
+          ((reverse ? (rss@[b]))@ls) (all_blank sig n) [ ]))).
+
+definition R_shift_i_L_new β‰ Ξ»sig,n,i,t1,t2.
+  (βˆ€a,ls,rs. 
+   t1 = midtape ? ls a rs  β†’ 
+   βˆƒrs1,b,rs2,rss.
+      b = hd ? rs2 (all_blank sig n) βˆ§
+      nth i ? (vec β€¦ b) (blank ?) = (blank ?) βˆ§
+      rs = rs1@rs2 βˆ§ 
+      (βˆ€x. mem ? x rs1 β†’ nth i ? (vec β€¦ x) (blank ?) β‰  (blank ?)) βˆ§
+      shift_l sig n i (a::rs1) rss βˆ§
+      t2 = midtape (multi_sig sig n) ((reverse ? rss)@ls) b (tail ? rs2)). 
+          
+theorem sem_shift_i_L: βˆ€sig,n,i. shift_i_L sig n i  βŠ¨ R_shift_i_L sig n i.
+#sig #n #i 
+@(sem_seq_app ?????? 
+  (sem_ncombf_r (multi_sig sig n) (shift_i sig n i)(all_blank sig n))
+   (sem_seq ????? (ssem_mti sig n i) 
+    (sem_extend ? (all_blank sig n))))
+#tin #tout * #t1 * * #Ht1a #Ht1b * #t2 * * #Ht2a #Ht2b * #Htout1 #Htout2
+#a #ls #rs cases rs
+  [#Htin %2 %{(shift_i sig n i a (all_blank sig n))} %{[ ]} 
+   %[%[#x @False_ind | @daemon]
+    |lapply (Ht1a β€¦ Htin) -Ht1a -Ht1b #Ht1 
+     lapply (Ht2a β€¦ Ht1) -Ht2a -Ht2b #Ht2 >Ht2 in Htout1; 
+     >Ht1 whd in match (left ??); whd in match (right ??); #Htout @Htout // 
+    ]
+  |#a1 #rs1 #Htin 
+   lapply (Ht1b β€¦ Htin) -Ht1a -Ht1b #Ht1 
+   lapply (Ht2b β€¦ Ht1) -Ht2a -Ht2b *
+    [(* a1 is blank *) * #H1 #H2 %1
+     %{[ ]} %{a1} %{rs1} %{(shift_i sig n i a a1)} %{[ ]}
+     %[%[%[%[// |//] |#x @False_ind] | @daemon]
+      |>Htout2 [>H2 >reverse_single @Ht1 |>H2 >Ht1 normalize % #H destruct (H)]
+      ]
+    |*
+    [* #rs10 * #b * #rs2 * #rss * * * * #H1 #H2 #H3 #H4
+     #Ht2 %1 
+     %{(a1::rs10)} %{b} %{rs2} %{(shift_i sig n i a a1)} %{rss}
+     %[%[%[%[>H1 //|//] |@H3] |@daemon ]
+      |>reverse_cons >associative_append 
+       >H2 in Htout2; #Htout >Htout [@Ht2| >Ht2 normalize % #H destruct (H)]  
+      ]
+    |* #b * #rss * * #H1 #H2 
+     #Ht2 %2
+     %{(shift_i sig n i b (all_blank sig n))} %{(shift_i sig n i a a1::rss)}
+     %[%[@H1 |@daemon ]
+      |>Ht2 in Htout1; #Htout >Htout //
+       whd in match (left ??); whd in match (right ??);
+       >reverse_append >reverse_single >associative_append  >reverse_cons
+       >associative_append // 
+       ]
+     ]
+   ]
+ ]
+qed.
+theorem sem_shift_i_L_new: βˆ€sig,n,i. 
+  shift_i_L sig n i  βŠ¨ R_shift_i_L_new sig n i.
+#sig #n #i 
+@(Realize_to_Realize β€¦ (sem_shift_i_L sig n i))
+#t1 #t2 #H #a #ls #rs #Ht1 lapply (H a ls rs Ht1) *
+  [* #rs1 * #b * #rs2 * #a1 * #rss * * * * #H1 #H2 #H3 #H4 #Ht2
+   %{rs1} %{b} %{(b::rs2)} %{(a1::rss)} 
+   %[%[%[%[%[//|@H2]|@H1]|@H3]|@H4] | whd in match (tail ??); @Ht2]
+  |* #b * #rss * * #H1 #H2 #Ht2
+   %{rs} %{(all_blank sig n)} %{[]} %{(rss@[b])} 
+   %[%[%[%[%[//|@blank_all_blank]|//]|@H1]|@H2] | whd in match (tail ??); @Ht2]
+  ]
+qed.
+   
+
+(*******************************************************************************
+The following machine implements a full move of for a trace: we reach the left 
+border, shift the i-th trace and come back to the head position. *)  
+
+(* this exclude the possibility that traces do not overlap: the head must 
+remain inside all traces *)
+
+definition mtiL β‰ Ξ»sig,n,i.
+   move_to_blank_L sig n i Β· 
+   shift_i_L sig n i Β·
+   move_until ? L (no_head sig n). 
+   
+definition Rmtil β‰ Ξ»sig,n,i,t1,t2.
+  βˆ€ls,a,rs. 
+   t1 = midtape (multi_sig sig n) ls a rs β†’ 
+   nth n ? (vec β€¦ a) (blank ?) = head ? β†’  
+   (βˆ€i.regular_trace sig n a ls rs i) β†’ 
+   (* next: we cannot be on rightof on trace i *)
+   (nth i ? (vec β€¦ a) (blank ?) = (blank ?) 
+     β†’ nth i ? (vec β€¦ (hd ? rs (all_blank β€¦))) (blank ?) β‰  (blank ?)) β†’
+   no_head_in β€¦ ls β†’   
+   no_head_in β€¦ rs  β†’ 
+   (βˆƒls1,a1,rs1.
+     t2 = midtape (multi_sig β€¦) ls1 a1 rs1 βˆ§
+     (βˆ€i.regular_trace β€¦ a1 ls1 rs1 i) βˆ§
+     (βˆ€j. j β‰€ n β†’ j β‰  i β†’ to_blank_i ? n j (a1::ls1) = to_blank_i ? n j (a::ls)) βˆ§
+     (βˆ€j. j β‰€ n β†’ j β‰  i β†’ to_blank_i ? n j rs1 = to_blank_i ? n j rs) βˆ§
+     (to_blank_i ? n i ls1 = to_blank_i ? n i (a::ls)) βˆ§
+     (to_blank_i ? n i (a1::rs1)) = to_blank_i ? n i rs).
+
+theorem sem_Rmtil: βˆ€sig,n,i. i < n β†’ mtiL sig n i  βŠ¨ Rmtil sig n i.
+#sig #n #i #lt_in
+@(sem_seq_app ?????? 
+  (sem_move_to_blank_L β€¦ )
+   (sem_seq ????? (sem_shift_i_L_new β€¦)
+    (ssem_move_until_L ? (no_head sig n))))
+#tin #tout * #t1 * * #_ #Ht1 * #t2 * #Ht2 * #_ #Htout
+(* we start looking into Rmitl *)
+#ls #a #rs #Htin (* tin is a midtape *)
+#Hhead #Hreg #no_rightof #Hnohead_ls #Hnohead_rs 
+cut (regular_i sig n (a::ls) i)
+  [cases (Hreg i) * // 
+   cases (true_or_false (nth i ? (vec β€¦ a) (blank ?) == (blank ?))) #Htest
+    [#_ @daemon (* absurd, since hd rs non e' blank *)
+    |#H #_ @daemon]] #Hreg1
+lapply (Ht1 β€¦ Htin Hreg1 ?) [#j #_ @Hreg] -Ht1 -Htin
+* #b * #ls1 * #ls2 * * * * * #reg_ls1_i #reg_ls1_j #Hno_blankb #Hhead #Hls1 #Ht1
+lapply (Ht2 β€¦ Ht1) -Ht2 -Ht1 
+* #rs1 * #b0 * #rs2 * #rss * * * * * #Hb0 #Hb0blank #Hrs1 #Hrs1b #Hrss #Ht2
+(* we need to recover the position of the head of the emulated machine
+   that is the head of ls1. This is somewhere inside rs1 *) 
+cut (βˆƒrs11. rs1 = (reverse ? ls1)@rs11)
+  [cut (ls1 = [ ] βˆ¨ βˆƒaa,tlls1. ls1 = aa::tlls1)
+    [cases ls1 [%1 // | #aa #tlls1 %2 %{aa} %{tlls1} //]] *
+      [#H1ls1 %{rs1} >H1ls1 //
+      |* #aa * #tlls1 #H1ls1 >H1ls1 in Hrs1; 
+       cut (aa = a) [>H1ls1 in Hls1; #H @(to_blank_hd β€¦ H)] #eqaa >eqaa  
+       #Hrs1_aux cases (compare_append β€¦ (sym_eq β€¦ Hrs1_aux)) #l *
+        [* #H1 #H2 %{l} @H1
+        |(* this is absurd : if l is empty, the case is as before.
+           if l is not empty then it must start with a blank, since it is the
+           first character in rs2. But in this case we would have a blank 
+           inside ls1=a::tls1 that is absurd *)
+          @daemon
+        ]]]   
+   * #rs11 #H1
+cut (rs = rs11@rs2)
+  [@(injective_append_l β€¦ (reverse β€¦ ls1)) >Hrs1 <associative_append <H1 //] #H2
+lapply (Htout β€¦ Ht2) -Htout -Ht2 *
+  [(* the current character on trace i holds the head-mark.
+      The case is absurd, since b0 is the head of rs2, that is a sublist of rs, 
+      and the head-mark is not in rs *)
+   * #H3 @False_ind @(absurd (nth n ? (vec β€¦ b0) (blank sig) = head ?)) 
+     [@(\P ?) @injective_notb @H3 ]
+   @Hnohead_rs >H2 >trace_append @mem_append_l2 
+   lapply Hb0 cases rs2 
+    [whd in match (hd ???); #H >H in H3; whd in match (no_head ???); 
+     >all_blank_n normalize -H #H destruct (H); @False_ind
+    |#c #r #H4 %1 >H4 //
+    ]
+  |* 
+  [(* we reach the head position *)
+   (* cut (trace sig n j (a1::ls20)=trace sig n j (ls1@b::ls2)) *)
+   * #ls10 * #a1 * #ls20 * * * #Hls20 #Ha1 #Hnh #Htout
+   cut (βˆ€j.j β‰  i β†’
+      trace sig n j (reverse (multi_sig sig n) rs1@b::ls2) = 
+      trace sig n j (ls10@a1::ls20))
+    [#j #ineqj >append_cons <reverse_cons >trace_def <map_append <reverse_map
+     lapply (trace_shift_neq β€¦lt_in ? (sym_not_eq β€¦ ineqj) β€¦ Hrss) [//] #Htr
+     <(trace_def β€¦  (b::rs1)) <Htr >reverse_map >map_append @eq_f @Hls20 ] 
+   #Htracej
+   cut (trace sig n i (reverse (multi_sig sig n) (rs1@[b0])@ls2) = 
+        trace sig n i (ls10@a1::ls20))
+    [>trace_def <map_append <reverse_map <map_append <(trace_def β€¦ [b0]) 
+     cut (trace sig n i [b0] = [blank ?]) [@daemon] #Hcut >Hcut
+     lapply (trace_shift β€¦ lt_in β€¦ Hrss) [//] whd in match (tail ??); #Htr <Htr
+     >reverse_map >map_append <trace_def <Hls20 % 
+    ] 
+   #Htracei
+   cut (βˆ€j. j β‰  i β†’
+      (trace sig n j (reverse (multi_sig sig n) rs11) = trace sig n j ls10) βˆ§ 
+      (trace sig n j (ls1@b::ls2) = trace sig n j (a1::ls20)))
+   [@daemon (* si fa 
+     #j #ineqj @(first_P_to_eq ? (Ξ»x. x β‰  head ?))
+      [lapply (Htracej β€¦ ineqj) >trace_def in βŠ’ (%β†’?); <map_append 
+       >trace_def in βŠ’ (%β†’?); <map_append #H @H  
+      | *) ] #H2
+  cut ((trace sig n i (b0::reverse ? rs11) = trace sig n i (ls10@[a1])) βˆ§ 
+      (trace sig n i (ls1@ls2) = trace sig n i ls20))
+   [>H1 in Htracei; >reverse_append >reverse_single >reverse_append 
+     >reverse_reverse >associative_append >associative_append
+     @daemon
+    ] #H3    
+  cut (βˆ€j. j β‰  i β†’ 
+    trace sig n j (reverse (multi_sig sig n) ls10@rs2) = trace sig n j rs)
+    [#j #jneqi @(injective_append_l β€¦ (trace sig n j (reverse ? ls1)))
+     >map_append >map_append >Hrs1 >H1 >associative_append 
+     <map_append <map_append in βŠ’ (???%); @eq_f 
+     <map_append <map_append @eq_f2 // @sym_eq 
+     <(reverse_reverse β€¦ rs11) <reverse_map <reverse_map in βŠ’ (???%);
+     @eq_f @(proj1 β€¦ (H2 j jneqi))] #Hrs_j
+   %{ls20} %{a1} %{(reverse ? (b0::ls10)@tail (multi_sig sig n) rs2)}
+   %[%[%[%[%[@Htout
+    |#j cases (decidable_eq_nat j i)
+      [#eqji >eqji (* by cases wether a1 is blank *)
+       @daemon
+      |#jneqi lapply (reg_ls1_j β€¦ jneqi) #H4 
+       >reverse_cons >associative_append >Hb0 @regular_cons_hd_rs
+       @(eq_trace_to_regular β€¦ H4)
+        [<hd_trace >(proj2 β€¦ (H2 β€¦ jneqi)) >hd_trace %
+        |<tail_trace >(proj2 β€¦ (H2 β€¦ jneqi)) >tail_trace %
+        |@sym_eq @Hrs_j //
+        ]
+      ]]
+    |#j #lejn #jneqi <(Hls1 β€¦ lejn) 
+     >to_blank_i_def >to_blank_i_def @eq_f @sym_eq @(proj2 β€¦ (H2 j jneqi))]
+    |#j #lejn #jneqi >reverse_cons >associative_append >Hb0
+     <to_blank_hd_cons >to_blank_i_def >to_blank_i_def @eq_f @Hrs_j //]
+    |<(Hls1 i) [2:@lt_to_le //] 
+     lapply (all_blank_after_blank β€¦ reg_ls1_i) 
+       [@(\P ?) @daemon] #allb_ls2
+     whd in match (to_blank_i ????); <(proj2 β€¦ H3)
+     @daemon ]
+    |>reverse_cons >associative_append  
+     cut (to_blank_i sig n i rs = to_blank_i sig n i (rs11@[b0])) [@daemon] 
+     #Hcut >Hcut >(to_blank_i_chop  β€¦ b0 (a1::reverse β€¦ls10)) [2: @Hb0blank]
+     >to_blank_i_def >to_blank_i_def @eq_f 
+     >trace_def >trace_def @injective_reverse >reverse_map >reverse_cons
+     >reverse_reverse >reverse_map >reverse_append >reverse_single @sym_eq
+     @(proj1 β€¦ H3)
+    ]
+  |(*we do not find the head: this is absurd *)
+   * #b1 * #lss * * #H2 @False_ind 
+   cut (βˆ€x0. mem ? x0 (trace sig n n (b0::reverse ? rss@ls2)) β†’ x0 β‰  head ?)
+     [@daemon] -H2 #H2
+   lapply (trace_shift_neq sig n i n β€¦ lt_in β€¦ Hrss)
+     [@lt_to_not_eq @lt_in | // ] 
+   #H3 @(absurd 
+        (nth n ? (vec β€¦ (hd ? (ls1@[b]) (all_blank sig n))) (blank ?) = head ?))
+     [>Hhead //
+     |@H2 >trace_def %2 <map_append @mem_append_l1 <reverse_map <trace_def 
+      >H3 >H1 >trace_def >reverse_map >reverse_cons >reverse_append 
+      >reverse_reverse >associative_append <map_append @mem_append_l2
+      cases ls1 [%1 % |#x #ll %1 %]
+     ]
+   ]
+ ]
+qed.
diff --git a/matita/matita/lib/binding/db.ma b/matita/matita/lib/binding/db.ma
deleted file mode 100644 (file)
index 534874f..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-(**************************************************************************)
-(*       ___                                                              *)
-(*      ||M||                                                             *)
-(*      ||A||       A project by Andrea Asperti                           *)
-(*      ||T||                                                             *)
-(*      ||I||       Developers:                                           *)
-(*      ||T||         The HELM team.                                      *)
-(*      ||A||         http://helm.cs.unibo.it                             *)
-(*      \   /                                                             *)
-(*       \ /        This file is distributed under the terms of the       *)
-(*        v         GNU General Public License Version 2                  *)
-(*                                                                        *)
-(**************************************************************************)
-
-include "basics/lists/list.ma".
-
-axiom alpha : Type[0].
-notation "𝔸" non associative with precedence 90 for @{'alphabet}.
-interpretation "set of names" 'alphabet = alpha.
-
-inductive tp : Type[0] β‰ 
-| top : tp
-| arr : tp β†’ tp β†’ tp.
-inductive tm : Type[0] β‰ 
-| var : nat β†’ tm
-| par :  π”Έ β†’ tm
-| abs : tp β†’ tm β†’ tm
-| app : tm β†’ tm β†’ tm.
-
-let rec Nth T n (l:list T) on n β‰ 
-  match l with 
-  [ nil β‡’ None ?
-  | cons hd tl β‡’ match n with
-    [ O β‡’ Some ? hd
-    | S n0 β‡’ Nth T n0 tl ] ].
-
-inductive judg : list tp β†’ tm β†’ tp β†’ Prop β‰ 
-| t_var : βˆ€g,n,t.Nth ? n g = Some ? t β†’ judg g (var n) t
-| t_app : βˆ€g,m,n,t,u.judg g m (arr t u) β†’ judg g n t β†’ judg g (app m n) u
-| t_abs : βˆ€g,t,m,u.judg (t::g) m u β†’ judg g (abs t m) (arr t u).
-
-definition Env := list (𝔸 Γ— tp).
-
-axiom vclose_env : Env β†’ list tp.
-axiom vclose_tm : Env β†’ tm β†’ tm.
-axiom Lam : π”Έ β†’ tp β†’ tm β†’ tm.
-definition Judg β‰ Ξ»G,M,T.judg (vclose_env G) (vclose_tm G M) T.
-definition dom β‰ Ξ»G:Env.map ?? (fst ??) G.
-
-definition sctx β‰ π”Έ Γ— tm.
-axiom swap_tm : π”Έ β†’ π”Έ β†’ tm β†’ tm.
-definition sctx_app : sctx β†’ π”Έ β†’ tm β‰ Ξ»M0,Y.let βŒ©X,MβŒͺ β‰ M0 in swap_tm X Y M.
-
-axiom in_list : βˆ€A:Type[0].A β†’ list A β†’ Prop.
-interpretation "list membership" 'mem x l = (in_list ? x l).
-interpretation "list non-membership" 'notmem x l = (Not (in_list ? x l)).
-
-axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
-notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
-interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
-
-let rec FV M β‰ match M with 
-  [ par X β‡’ [X]
-  | app M1 M2 β‡’ FV M1@FV M2
-  | abs T M0 β‡’ FV M0
-  | _ β‡’ [ ] ].
-
-(* axiom Lookup : π”Έ β†’ Env β†’ option tp. *)
-
-(* forma alto livello del judgment
-   t_abs* : βˆ€G,T,X,M,U.
-            (βˆ€Y βˆ‰ supp(M).Judg (〈Y,TβŒͺ::G) (M[Y]) U) β†’ 
-            Judg G (Lam X T (M[X])) (arr T U) *)
-
-(* prima dimostrare, poi perfezionare gli assiomi, poi dimostrarli *)
-
-axiom Judg_ind : βˆ€P:Env β†’ tm β†’ tp β†’ Prop.
-  (βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ P G (par X) T) β†’ 
-  (βˆ€G,M,N,T,U.
-    Judg G M (arr T U) β†’ Judg G N T β†’ 
-    P G M (arr T U) β†’ P G N T β†’ P G (app M N) U) β†’ 
-  (βˆ€G,T1,T2,X,M1.
-    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ Judg (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’
-    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ P (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’ 
-    P G (Lam X T1 (sctx_app M1 X)) (arr T1 T2)) β†’ 
-  βˆ€G,M,T.Judg G M T β†’ P G M T.
-
-axiom t_par : βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ Judg G (par X) T.
-axiom t_app2 : βˆ€G,M,N,T,U.Judg G M (arr T U) β†’ Judg G N T β†’ Judg G (app M N) U.
-axiom t_Lam : βˆ€G,X,M,T,U.Judg (〈X,TβŒͺ::G) M U β†’ Judg G (Lam X T M) (arr T U).
-
-definition subenv β‰ Ξ»G1,G2.βˆ€x.x β—ƒ G1 β†’ x β—ƒ G2.
-interpretation "subenv" 'subseteq G1 G2 = (subenv G1 G2).
-
-axiom daemon : βˆ€P:Prop.P.
-
-theorem weakening : βˆ€G1,G2,M,T.G1 βŠ† G2 β†’ Judg G1 M T β†’ Judg G2 M T.
-#G1 #G2 #M #T #Hsub #HJ lapply Hsub lapply G2 -G2 change with (βˆ€G2.?)
-@(Judg_ind β€¦ HJ)
-[ #X #G #T0 #Hin #G2 #Hsub @t_par @Hsub //
-| #G #M0 #N #T0 #U #HM0 #HN #IH1 #IH2 #G2 #Hsub @t_app2
-  [| @IH1 // | @IH2 // ]
-| #G #T1 #T2 #X #M1 #HM1 #IH #G2 #Hsub @t_Lam @IH 
-  [ (* trivial property of Lam *) @daemon 
-  | (* trivial property of subenv *) @daemon ]
-]
-qed.
-
-(* Serve un tipo Tm per i termini localmente chiusi e i suoi principi di induzione e
-   ricorsione *)
\ No newline at end of file
diff --git a/matita/matita/lib/binding/fp.ma b/matita/matita/lib/binding/fp.ma
deleted file mode 100644 (file)
index 14ba2f7..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-(**************************************************************************)
-(*       ___                                                              *)
-(*      ||M||                                                             *)
-(*      ||A||       A project by Andrea Asperti                           *)
-(*      ||T||                                                             *)
-(*      ||I||       Developers:                                           *)
-(*      ||T||         The HELM team.                                      *)
-(*      ||A||         http://helm.cs.unibo.it                             *)
-(*      \   /                                                             *)
-(*       \ /        This file is distributed under the terms of the       *)
-(*        v         GNU General Public License Version 2                  *)
-(*                                                                        *)
-(**************************************************************************)
-
-include "binding/names.ma".
-
-(* permutations *)
-definition finite_perm : βˆ€X:Nset.(X β†’ X) β†’ Prop β‰ 
- Ξ»X,f.injective X X f βˆ§ surjective X X f βˆ§ βˆƒl.βˆ€x.x βˆ‰ l β†’ f x = x.
-
-(* maps a permutation to a list of parameters *)
-definition Pi_list : βˆ€X:Nset.(X β†’ X) β†’ list X β†’ list X β‰ 
- Ξ»X,p,xl.map ?? (Ξ»x.p x) xl.
-
-interpretation "permutation of X list" 'middot p x = (Pi_list p x).
-
-definition swap : βˆ€N:Nset.N β†’ N β†’ N β†’ N β‰
-  Ξ»N,u,v,x.match (x == u) with
-    [true β‡’ v
-    |false β‡’ match (x == v) with
-       [true β‡’ u
-       |false β‡’ x]].
-       
-axiom swap_right : βˆ€N,x,y.swap N x y y = x.
-(*
-#N x y;nnormalize;nrewrite > (p_eqb3 ? y y β€¦);//;
-nlapply (refl ? (y β‰Ÿ x));ncases (y β‰Ÿ x) in βŠ’ (???% β†’ %);nnormalize;//;
-#H1;napply p_eqb1;//;
-nqed.
-*)
-
-axiom swap_left : βˆ€N,x,y.swap N x y x = y.
-(*
-#N x y;nnormalize;nrewrite > (p_eqb3 ? x x β€¦);//;
-nqed.
-*)
-
-axiom swap_other : βˆ€N,x,y,z.x β‰  z β†’ y β‰  z β†’ swap N x y z = z.
-(*
-#N x y z H1 H2;nnormalize;nrewrite > (p_eqb4 β€¦);
-##[nrewrite > (p_eqb4 β€¦);//;@;ncases H2;/2/;
-##|@;ncases H1;/2/
-##]
-nqed.
-*)
-
-axiom swap_inv : βˆ€N,x,y,z.swap N x y (swap N x y z) = z.
-(*
-#N x y z;nlapply (refl ? (x β‰Ÿ z));ncases (x β‰Ÿ z) in βŠ’ (???% β†’ ?);#H1
-##[nrewrite > (p_eqb1 β€¦ H1);nrewrite > (swap_left β€¦);//;
-##|nlapply (refl ? (y β‰Ÿ z));ncases (y β‰Ÿ z) in βŠ’ (???% β†’ ?);#H2
-   ##[nrewrite > (p_eqb1 β€¦ H2);nrewrite > (swap_right β€¦);//;
-   ##|nrewrite > (swap_other β€¦) in βŠ’ (??(????%)?);/2/;
-      nrewrite > (swap_other β€¦);/2/;
-   ##]
-##]
-nqed.
-*)
-
-axiom swap_fp : βˆ€N,x1,x2.finite_perm ? (swap N x1 x2).
-(*
-#N x1 x2;@
-##[@
-   ##[nwhd;#xa xb;nnormalize;nlapply (refl ? (xa β‰Ÿ x1));
-      ncases (xa β‰Ÿ x1) in βŠ’ (???% β†’ %);#H1
-      ##[nrewrite > (p_eqb1 β€¦ H1);nlapply (refl ? (xb β‰Ÿ x1));
-         ncases (xb β‰Ÿ x1) in βŠ’ (???% β†’ %);#H2
-         ##[nrewrite > (p_eqb1 β€¦ H2);//
-         ##|nlapply (refl ? (xb β‰Ÿ x2));
-            ncases (xb β‰Ÿ x2) in βŠ’ (???% β†’ %);#H3
-            ##[nnormalize;#H4;nrewrite > H4 in H3;
-               #H3;nrewrite > H3 in H2;#H2;ndestruct (H2)
-            ##|nnormalize;#H4;nrewrite > H4 in H3;
-               nrewrite > (p_eqb3 β€¦);//;#H5;ndestruct (H5)
-            ##]
-         ##]
-      ##|nlapply (refl ? (xa β‰Ÿ x2));
-         ncases (xa β‰Ÿ x2) in βŠ’ (???% β†’ %);#H2
-         ##[nrewrite > (p_eqb1 β€¦ H2);nlapply (refl ? (xb β‰Ÿ x1));
-            ncases (xb β‰Ÿ x1) in βŠ’ (???% β†’ %);#H3
-            ##[nnormalize;#H4;nrewrite > H4 in H3;
-               #H3;nrewrite > (p_eqb1 β€¦ H3);@
-            ##|nnormalize;nlapply (refl ? (xb β‰Ÿ x2));
-               ncases (xb β‰Ÿ x2) in βŠ’ (???% β†’ %);#H4
-               ##[nrewrite > (p_eqb1 β€¦ H4);//
-               ##|nnormalize;#H5;nrewrite > H5 in H3;
-                  nrewrite > (p_eqb3 β€¦);//;#H6;ndestruct (H6);
-               ##]
-            ##]
-         ##|nnormalize;nlapply (refl ? (xb β‰Ÿ x1));
-            ncases (xb β‰Ÿ x1) in βŠ’ (???% β†’ %);#H3
-            ##[nnormalize;#H4;nrewrite > H4 in H2;nrewrite > (p_eqb3 β€¦);//;
-               #H5;ndestruct (H5)
-            ##|nlapply (refl ? (xb β‰Ÿ x2));
-               ncases (xb β‰Ÿ x2) in βŠ’ (???% β†’ %);#H4
-               ##[nnormalize;#H5;nrewrite > H5 in H1;nrewrite > (p_eqb3 β€¦);//;
-                  #H6;ndestruct (H6)
-               ##|nnormalize;//
-               ##]
-            ##]
-         ##]
-      ##]
-   ##|nwhd;#z;nnormalize;nlapply (refl ? (z β‰Ÿ x1));
-      ncases (z β‰Ÿ x1) in βŠ’ (???% β†’ %);#H1
-      ##[nlapply (refl ? (z β‰Ÿ x2));
-         ncases (z β‰Ÿ x2) in βŠ’ (???% β†’ %);#H2
-         ##[@ z;nrewrite > H1;nrewrite > H2;napply p_eqb1;//
-         ##|@ x2;nrewrite > (p_eqb4 β€¦);
-            ##[nrewrite > (p_eqb3 β€¦);//;
-               nnormalize;napply p_eqb1;//
-            ##|nrewrite < (p_eqb1 β€¦ H1);@;#H3;nrewrite > H3 in H2;
-               nrewrite > (p_eqb3 β€¦);//;#H2;ndestruct (H2)
-            ##]
-         ##]
-      ##|nlapply (refl ? (z β‰Ÿ x2));
-         ncases (z β‰Ÿ x2) in βŠ’ (???% β†’ %);#H2
-         ##[@ x1;nrewrite > (p_eqb3 β€¦);//;
-            napply p_eqb1;nnormalize;//
-         ##|@ z;nrewrite > H1;nrewrite > H2;@;
-         ##]
-      ##]
-   ##]
-##|@ [x1;x2];#x0 H1;nrewrite > (swap_other β€¦)
-   ##[@
-   ##|@;#H2;nrewrite > H2 in H1;*;#H3;napply H3;/2/;
-   ##|@;#H2;nrewrite > H2 in H1;*;#H3;napply H3;//;
-   ##]
-##]
-nqed.
-*)
-
-axiom inj_swap : βˆ€N,u,v.injective ?? (swap N u v).
-(*
-#N u v;ncases (swap_fp N u v);*;#H1 H2 H3;//;
-nqed.
-*)
-
-axiom surj_swap : βˆ€N,u,v.surjective ?? (swap N u v).
-(*
-#N u v;ncases (swap_fp N u v);*;#H1 H2 H3;//;
-nqed.
-*)
-
-axiom finite_swap : βˆ€N,u,v.βˆƒl.βˆ€x.x βˆ‰ l β†’ swap N u v x = x.
-(*
-#N u v;ncases (swap_fp N u v);*;#H1 H2 H3;//;
-nqed.
-*)
-
-(* swaps two lists of parameters 
-definition Pi_swap_list : βˆ€xl,xl':list X.X β†’ X β‰ 
- Ξ»xl,xl',x.foldr2 ??? (Ξ»u,v,r.swap ? u v r) x xl xl'.
-
-nlemma fp_swap_list : 
-  βˆ€xl,xl'.finite_perm ? (Pi_swap_list xl xl').
-#xl xl';@
-##[@;
-   ##[ngeneralize in match xl';nelim xl
-      ##[nnormalize;//;
-      ##|#x0 xl0;#IH xl'';nelim xl''
-         ##[nnormalize;//
-         ##|#x1 xl1 IH1 y0 y1;nchange in βŠ’ (??%% β†’ ?) with (swap ????);
-            #H1;nlapply (inj_swap β€¦ H1);#H2;
-            nlapply (IH β€¦ H2);//
-         ##]
-      ##]
-   ##|ngeneralize in match xl';nelim xl
-      ##[nnormalize;#_;#z;@z;@
-      ##|#x' xl0 IH xl'';nelim xl''
-         ##[nnormalize;#z;@z;@
-         ##|#x1 xl1 IH1 z;
-            nchange in βŠ’ (??(Ξ»_.???%)) with (swap ????);
-            ncases (surj_swap X x' x1 z);#x2 H1;
-            ncases (IH xl1 x2);#x3 H2;@ x3;
-            nrewrite < H2;napply H1
-         ##]
-      ##]
-   ##]
-##|ngeneralize in match xl';nelim xl
-   ##[#;@ [];#;@
-   ##|#x0 xl0 IH xl'';ncases xl''
-      ##[@ [];#;@
-      ##|#x1 xl1;ncases (IH xl1);#xl2 H1;
-         ncases (finite_swap X x0 x1);#xl3 H2;
-         @ (xl2@xl3);#x2 H3;
-         nchange in βŠ’ (??%?) with (swap ????);
-         nrewrite > (H1 β€¦);
-         ##[nrewrite > (H2 β€¦);//;@;#H4;ncases H3;#H5;napply H5;
-            napply in_list_to_in_list_append_r;//
-         ##|@;#H4;ncases H3;#H5;napply H5;
-            napply in_list_to_in_list_append_l;//
-         ##]
-      ##]
-   ##]
-##]
-nqed.
-
-(* the 'reverse' swap of lists of parameters 
-   composing Pi_swap_list and Pi_swap_list_r yields the identity function
-   (see the Pi_swap_list_inv lemma) *)
-ndefinition Pi_swap_list_r : βˆ€xl,xl':list X. Pi β‰ 
- Ξ»xl,xl',x.foldl2 ??? (Ξ»r,u,v.swap ? u v r ) x xl xl'.
-
-nlemma fp_swap_list_r : 
-  βˆ€xl,xl'.finite_perm ? (Pi_swap_list_r xl xl').
-#xl xl';@
-##[@;
-   ##[ngeneralize in match xl';nelim xl
-      ##[nnormalize;//;
-      ##|#x0 xl0;#IH xl'';nelim xl''
-         ##[nnormalize;//
-         ##|#x1 xl1 IH1 y0 y1;nwhd in βŠ’ (??%% β†’ ?);
-            #H1;nlapply (IH β€¦ H1);#H2;
-            napply (inj_swap β€¦ H2);
-         ##]
-      ##]
-   ##|ngeneralize in match xl';nelim xl
-      ##[nnormalize;#_;#z;@z;@
-      ##|#x' xl0 IH xl'';nelim xl''
-         ##[nnormalize;#z;@z;@
-         ##|#x1 xl1 IH1 z;nwhd in βŠ’ (??(Ξ»_.???%));
-            ncases (IH xl1 z);#x2 H1;
-            ncases (surj_swap X x' x1 x2);#x3 H2;
-            @ x3;nrewrite < H2;napply H1;
-         ##]
-      ##]
-   ##]
-##|ngeneralize in match xl';nelim xl
-   ##[#;@ [];#;@
-   ##|#x0 xl0 IH xl'';ncases xl''
-      ##[@ [];#;@
-      ##|#x1 xl1;
-         ncases (IH xl1);#xl2 H1;
-         ncases (finite_swap X x0 x1);#xl3 H2;
-         @ (xl2@xl3);#x2 H3;nwhd in βŠ’ (??%?);
-         nrewrite > (H2 β€¦);
-         ##[nrewrite > (H1 β€¦);//;@;#H4;ncases H3;#H5;napply H5;
-            napply in_list_to_in_list_append_l;//
-         ##|@;#H4;ncases H3;#H5;napply H5;
-            napply in_list_to_in_list_append_r;//
-         ##]
-      ##]
-   ##]
-##]
-nqed.
-
-nlemma Pi_swap_list_inv :
- βˆ€xl1,xl2,x.
- Pi_swap_list xl1 xl2 (Pi_swap_list_r xl1 xl2 x) = x.
-#xl;nelim xl
-##[#;@
-##|#x1 xl1 IH xl';ncases xl'
-   ##[#;@
-   ##|#x2 xl2;#x;
-      nchange in βŠ’ (??%?) with 
-        (swap ??? (Pi_swap_list ?? 
-                  (Pi_swap_list_r ?? (swap ????))));
-      nrewrite > (IH xl2 ?);napply swap_inv;
-   ##]
-##]
-nqed.
-
-nlemma Pi_swap_list_fresh :
-  βˆ€x,xl1,xl2.x βˆ‰ xl1 β†’ x βˆ‰ xl2 β†’ Pi_swap_list xl1 xl2 x = x.
-#x xl1;nelim xl1
-##[#;@
-##|#x3 xl3 IH xl2' H1;ncases xl2'
-   ##[#;@
-   ##|#x4 xl4 H2;ncut (x βˆ‰ xl3 βˆ§ x βˆ‰ xl4);
-      ##[@
-         ##[@;#H3;ncases H1;#H4;napply H4;/2/;
-         ##|@;#H3;ncases H2;#H4;napply H4;/2/
-         ##]
-      ##] *; #H1' H2';
-      nchange in βŠ’ (??%?) with (swap ????);
-      nrewrite > (swap_other β€¦)
-      ##[napply IH;//;
-      ##|nchange in βŠ’ (?(???%)) with (Pi_swap_list ???);
-         nrewrite > (IH β€¦);//;@;#H3;ncases H2;#H4;napply H4;//;
-      ##|nchange in βŠ’ (?(???%)) with (Pi_swap_list ???);
-         nrewrite > (IH β€¦);//;@;#H3;ncases H1;#H4;napply H4;//
-      ##]
-   ##]
-##]
-nqed.
-*)
\ No newline at end of file
diff --git a/matita/matita/lib/binding/ln.ma b/matita/matita/lib/binding/ln.ma
deleted file mode 100644 (file)
index ca7f574..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-(**************************************************************************)
-(*       ___                                                              *)
-(*      ||M||                                                             *)
-(*      ||A||       A project by Andrea Asperti                           *)
-(*      ||T||                                                             *)
-(*      ||I||       Developers:                                           *)
-(*      ||T||         The HELM team.                                      *)
-(*      ||A||         http://helm.cs.unibo.it                             *)
-(*      \   /                                                             *)
-(*       \ /        This file is distributed under the terms of the       *)
-(*        v         GNU General Public License Version 2                  *)
-(*                                                                        *)
-(**************************************************************************)
-
-include "basics/lists/list.ma".
-include "basics/deqsets.ma".
-include "binding/names.ma".
-include "binding/fp.ma".
-
-axiom alpha : Nset.
-notation "𝔸" non associative with precedence 90 for @{'alphabet}.
-interpretation "set of names" 'alphabet = alpha.
-
-inductive tp : Type[0] β‰ 
-| top : tp
-| arr : tp β†’ tp β†’ tp.
-inductive pretm : Type[0] β‰ 
-| var : nat β†’ pretm
-| par :  π”Έ β†’ pretm
-| abs : tp β†’ pretm β†’ pretm
-| app : pretm β†’ pretm β†’ pretm.
-
-let rec Nth T n (l:list T) on n β‰ 
-  match l with 
-  [ nil β‡’ None ?
-  | cons hd tl β‡’ match n with
-    [ O β‡’ Some ? hd
-    | S n0 β‡’ Nth T n0 tl ] ].
-
-let rec vclose_tm_aux u x k β‰ match u with
-  [ var n β‡’ if (leb k n) then var (S n) else u
-  | par x0 β‡’ if (x0 == x) then (var k) else u
-  | app v1 v2 β‡’ app (vclose_tm_aux v1 x k) (vclose_tm_aux v2 x k)
-  | abs s v β‡’ abs s (vclose_tm_aux v x (S k)) ].
-definition vclose_tm β‰ Ξ»u,x.vclose_tm_aux u x O.  
-
-definition vopen_var β‰ Ξ»n,x,k.match eqb n k with
- [ true β‡’ par x
- | false β‡’ match leb n k with
-   [ true β‡’ var n
-   | false β‡’ var (pred n) ] ].
-
-let rec vopen_tm_aux u x k β‰ match u with
-  [ var n β‡’ vopen_var n x k
-  | par x0 β‡’ u
-  | app v1 v2 β‡’ app (vopen_tm_aux v1 x k) (vopen_tm_aux v2 x k)
-  | abs s v β‡’ abs s (vopen_tm_aux v x (S k)) ].
-definition vopen_tm β‰ Ξ»u,x.vopen_tm_aux u x O.
-
-let rec FV u β‰ match u with 
-  [ par x β‡’ [x]
-  | app v1 v2 β‡’ FV v1@FV v2
-  | abs s v β‡’ FV v
-  | _ β‡’ [ ] ].  
-
-definition lam β‰ Ξ»x,s,u.abs s (vclose_tm u x).
-
-let rec Pi_map_tm p u on u β‰ match u with
-[ par x β‡’ par (p x)
-| var _ β‡’ u
-| app v1 v2 β‡’ app (Pi_map_tm p v1) (Pi_map_tm p v2)
-| abs s v β‡’ abs s (Pi_map_tm p v) ].
-
-interpretation "permutation of tm" 'middot p x = (Pi_map_tm p x).
-
-notation "hvbox(u⌈xβŒ‰)"
-  with precedence 45
-  for @{ 'open $u $x }.
-
-(*
-notation "hvbox(u⌈xβŒ‰)"
-  with precedence 45
-  for @{ 'open $u $x }.
-notation "❴ u β΅ x" non associative with precedence 90 for @{ 'open $u $x }.
-*)
-interpretation "ln term variable open" 'open u x = (vopen_tm u x).
-notation < "hvbox(Ξ½ x break . u)"
- with precedence 20
-for @{'nu $x $u }.
-notation > "Ξ½ list1 x sep , . term 19 u" with precedence 20
-  for ${ fold right @{$u} rec acc @{'nu $x $acc)} }.
-interpretation "ln term variable close" 'nu x u = (vclose_tm u x).
-
-let rec tm_height u β‰ match u with
-[ app v1 v2 β‡’ S (max (tm_height v1) (tm_height v2))
-| abs s v β‡’ S (tm_height v) 
-| _ β‡’ O ].
-
-theorem le_n_O_rect_Type0 : βˆ€n:nat. n β‰€ O β†’ βˆ€P: nat β†’Type[0]. P O β†’ P n.
-#n (cases n) // #a #abs cases (?:False) /2/ qed. 
-
-theorem nat_rect_Type0_1 : βˆ€n:nat.βˆ€P:nat β†’ Type[0]. 
-(βˆ€m.(βˆ€p. p < m β†’ P p) β†’ P m) β†’ P n.
-#n #P #H 
-cut (βˆ€q:nat. q β‰€ n β†’ P q) /2/
-(elim n) 
- [#q #HleO (* applica male *) 
-    @(le_n_O_rect_Type0 ? HleO)
-    @H #p #ltpO cases (?:False) /2/ (* 3 *)
- |#p #Hind #q #HleS 
-    @H #a #lta @Hind @le_S_S_to_le /2/
- ]
-qed.
-
-lemma leb_false_to_lt : βˆ€n,m. leb n m = false β†’ m < n.
-#n elim n
-[ #m normalize #H destruct(H)
-| #n0 #IH * // #m normalize #H @le_S_S @IH // ]
-qed.
-
-lemma nominal_eta_aux : βˆ€x,u.x βˆ‰ FV u β†’ βˆ€k.vclose_tm_aux (vopen_tm_aux u x k) x k = u.
-#x #u elim u
-[ #n #_ #k normalize cases (decidable_eq_nat n k) #Hnk
-  [ >Hnk >eqb_n_n normalize >(\b ?) //
-  | >(not_eq_to_eqb_false β€¦ Hnk) normalize cases (true_or_false (leb n k)) #Hleb
-    [ >Hleb normalize >(?:leb k n = false) //
-      @lt_to_leb_false @not_eq_to_le_to_lt /2/
-    | >Hleb normalize >(?:leb k (pred n) = true) normalize
-      [ cases (leb_false_to_lt β€¦ Hleb) //
-      | @le_to_leb_true cases (leb_false_to_lt β€¦ Hleb) normalize /2/ ] ] ]
-| #y normalize #Hy >(\bf ?) // @(not_to_not β€¦ Hy) //
-| #s #v #IH normalize #Hv #k >IH // @Hv
-| #v1 #v2 #IH1 #IH2 normalize #Hv1v2 #k 
-  >IH1 [ >IH2 // | @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_l ]
-  @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_r ]
-qed.
-
-corollary nominal_eta : βˆ€x,u.x βˆ‰ FV u β†’ (Ξ½x.u⌈xβŒ‰) = u.
-#x #u #Hu @nominal_eta_aux //
-qed.
-
-lemma eq_height_vopen_aux : βˆ€v,x,k.tm_height (vopen_tm_aux v x k) = tm_height v.
-#v #x elim v
-[ #n #k normalize cases (eqb n k) // cases (leb n k) //
-| #u #k %
-| #s #u #IH #k normalize >IH %
-| #u1 #u2 #IH1 #IH2 #k normalize >IH1 >IH2 % ]
-qed.
-
-corollary eq_height_vopen : βˆ€v,x.tm_height (v⌈xβŒ‰) = tm_height v.
-#v #x @eq_height_vopen_aux
-qed.
-
-theorem pretm_ind_plus_aux : 
- βˆ€P:pretm β†’ Type[0].
-   (βˆ€x:𝔸.P (par x)) β†’ 
-   (βˆ€n:β„•.P (var n)) β†’ 
-   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
- βˆ€n,u.tm_height u β‰€ n β†’ P u.
-#P #Hpar #Hvar #Happ #C #Hlam #n change with ((Ξ»n.?) n); @(nat_rect_Type0_1 n ??)
-#m cases m
-[ #_ * /2/
-  [ normalize #s #v #Hfalse cases (?:False) cases (not_le_Sn_O (tm_height v)) /2/
-  | #v1 #v2 whd in βŠ’ (?%?β†’?); #Hfalse cases (?:False) cases (not_le_Sn_O (max ??))
-    [ #H @H @Hfalse|*:skip] ] ]
--m #m #IH * /2/
-[ #s #v whd in βŠ’ (?%?β†’?); #Hv
-  lapply (p_fresh β€¦ (C@FV v)) letin y β‰ (N_fresh β€¦ (C@FV v)) #Hy
-  >(?:abs s v = lam y s (v⌈yβŒ‰))
-  [| whd in βŠ’ (???%); >nominal_eta // @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r ] 
-  @Hlam
-  [ @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r
-  | @(not_to_not β€¦ Hy) @in_list_to_in_list_append_l ]
-  @IH [| @Hv | >eq_height_vopen % ]
-| #v1 #v2 whd in βŠ’ (?%?β†’?); #Hv @Happ
-  [ @IH [| @Hv | @le_max_1 ] | @IH [| @Hv | @le_max_2 ] ] ]
-qed.
-
-corollary pretm_ind_plus :
- βˆ€P:pretm β†’ Type[0].
-   (βˆ€x:𝔸.P (par x)) β†’ 
-   (βˆ€n:β„•.P (var n)) β†’ 
-   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
- βˆ€u.P u.
-#P #Hpar #Hvar #Happ #C #Hlam #u @pretm_ind_plus_aux /2/
-qed.
-
-(* maps a permutation to a list of terms *)
-definition Pi_map_list : (𝔸 β†’ π”Έ) β†’ list π”Έ β†’ list π”Έ β‰ map π”Έ π”Έ .
-
-(* interpretation "permutation of name list" 'middot p x = (Pi_map_list p x).*)
-
-(*
-inductive tm : pretm β†’ Prop β‰ 
-| tm_par : βˆ€x:𝔸.tm (par x)
-| tm_app : βˆ€u,v.tm u β†’ tm v β†’ tm (app u v)
-| tm_lam : βˆ€x,s,u.tm u β†’ tm (lam x s u).
-
-inductive ctx_aux : nat β†’ pretm β†’ Prop β‰ 
-| ctx_var : βˆ€n,k.n < k β†’ ctx_aux k (var n)
-| ctx_par : βˆ€x,k.ctx_aux k (par x)
-| ctx_app : βˆ€u,v,k.ctx_aux k u β†’ ctx_aux k v β†’ ctx_aux k (app u v)
-(* Γ¨ sostituibile da ctx_lam ? *)
-| ctx_abs : βˆ€s,u.ctx_aux (S k) u β†’ ctx_aux k (abs s u).
-*)
-
-inductive tm_or_ctx (k:nat) : pretm β†’ Type[0] β‰ 
-| toc_var : βˆ€n.n < k β†’ tm_or_ctx k (var n)
-| toc_par : βˆ€x.tm_or_ctx k (par x)
-| toc_app : βˆ€u,v.tm_or_ctx k u β†’ tm_or_ctx k v β†’ tm_or_ctx k (app u v)
-| toc_lam : βˆ€x,s,u.tm_or_ctx k u β†’ tm_or_ctx k (lam x s u).
-
-definition tm β‰ Ξ»t.tm_or_ctx O t.
-definition ctx β‰ Ξ»t.tm_or_ctx 1 t.
-
-definition check_tm β‰ Ξ»u,k.
-  pretm_ind_plus ?
-  (Ξ»_.true)
-  (Ξ»n.leb (S n) k)
-  (Ξ»v1,v2,rv1,rv2.rv1 βˆ§ rv2)
-  [] (Ξ»x,s,v,px,pC,rv.rv)
-  u.
-
-axiom pretm_ind_plus_app : βˆ€P,u,v,C,H1,H2,H3,H4.
-  pretm_ind_plus P H1 H2 H3 C H4 (app u v) = 
-    H3 u v (pretm_ind_plus P H1 H2 H3 C H4 u) (pretm_ind_plus P H1 H2 H3 C H4 v).
-
-axiom pretm_ind_plus_lam : βˆ€P,x,s,u,C,px,pC,H1,H2,H3,H4.
-  pretm_ind_plus P H1 H2 H3 C H4 (lam x s (u⌈xβŒ‰)) = 
-    H4 x s u px pC (pretm_ind_plus P H1 H2 H3 C H4 (u⌈xβŒ‰)).
-
-record TM : Type[0] β‰ {
-  pretm_of_TM :> pretm;
-  tm_of_TM : check_tm pretm_of_TM O = true
-}.
-
-record CTX : Type[0] β‰ {
-  pretm_of_CTX :> pretm;
-  ctx_of_CTX : check_tm pretm_of_CTX 1 = true
-}.
-
-inductive tm2 : pretm β†’ Type[0] β‰ 
-| tm_par : βˆ€x.tm2 (par x)
-| tm_app : βˆ€u,v.tm2 u β†’ tm2 v β†’ tm2 (app u v)
-| tm_lam : βˆ€x,s,u.x βˆ‰ FV u β†’ (βˆ€y.y βˆ‰ FV u β†’ tm2 (u⌈yβŒ‰)) β†’ tm2 (lam x s (u⌈xβŒ‰)).
-
-(*
-inductive tm' : pretm β†’ Prop β‰ 
-| tm_par : βˆ€x.tm' (par x)
-| tm_app : βˆ€u,v.tm' u β†’ tm' v β†’ tm' (app u v)
-| tm_lam : βˆ€x,s,u,C.x βˆ‰ FV u β†’ x βˆ‰ C β†’ (βˆ€y.y βˆ‰ FV u β†’ tm' (❴u❡y)) β†’ tm' (lam x s (❴u❡x)).
-*)
-
-lemma pi_vclose_tm : 
-  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(Ξ½x.u) = (Ξ½ swap ? z1 z2 x.swap π”Έ z1 z2 Β· u).
-#z1 #z2 #x #u
-change with (vclose_tm_aux ???) in match (vclose_tm ??);
-change with (vclose_tm_aux ???) in βŠ’ (???%); lapply O elim u normalize //
-[ #n #k cases (leb k n) normalize %
-| #x0 #k cases (true_or_false (x0==z1)) #H1 >H1 normalize
-  [ cases (true_or_false (x0==x)) #H2 >H2 normalize
-    [ <(\P H2) >H1 normalize >(\b (refl ? z2)) %
-    | >H1 normalize cases (true_or_false (x==z1)) #H3 >H3 normalize
-      [ >(\P H3) in H2; >H1 #Hfalse destruct (Hfalse)
-      | cases (true_or_false (x==z2)) #H4 >H4 normalize
-        [ cases (true_or_false (z2==z1)) #H5 >H5 normalize //
-          >(\P H5) in H4; >H3 #Hfalse destruct (Hfalse)
-        | >(\bf ?) // @sym_not_eq @(\Pf H4) ]
-      ]
-    ]
-  | cases (true_or_false (x0==x)) #H2 >H2 normalize
-    [ <(\P H2) >H1 normalize >(\b (refl ??)) %
-    | >H1 normalize cases (true_or_false (x==z1)) #H3 >H3 normalize
-      [ cases (true_or_false (x0==z2)) #H4 >H4 normalize 
-        [ cases (true_or_false (z1==z2)) #H5 >H5 normalize //
-          <(\P H5) in H4; <(\P H3) >H2 #Hfalse destruct (Hfalse)
-        | >H4 % ]
-      | cases (true_or_false (x0==z2)) #H4 >H4 normalize
-        [ cases (true_or_false (x==z2)) #H5 >H5 normalize 
-          [ <(\P H5) in H4; >H2 #Hfalse destruct (Hfalse)
-          | >(\bf ?) // @sym_not_eq @(\Pf H3) ]
-        | cases (true_or_false (x==z2)) #H5 >H5 normalize
-          [ >H1 %
-          | >H2 % ]
-        ]
-      ]
-    ]
-  ]
-]
-qed.
-
-lemma pi_vopen_tm : 
-  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(u⌈xβŒ‰) = (swap π”Έ z1 z2 Β· u⌈swap π”Έ z1 z2 xβŒ‰).
-#z1 #z2 #x #u
-change with (vopen_tm_aux ???) in match (vopen_tm ??);
-change with (vopen_tm_aux ???) in βŠ’ (???%); lapply O elim u normalize //
-#n #k cases (true_or_false (eqb n k)) #H1 >H1 normalize //
-cases (true_or_false (leb n k)) #H2 >H2 normalize //
-qed.
-
-lemma pi_lam : 
-  βˆ€z1,z2,x,s,u.swap π”Έ z1 z2 Β· lam x s u = lam (swap π”Έ z1 z2 x) s (swap π”Έ z1 z2 Β· u).
-#z1 #z2 #x #s #u whd in βŠ’ (???%); <(pi_vclose_tm β€¦) %
-qed.
-
-lemma eqv_FV : βˆ€z1,z2,u.FV (swap π”Έ z1 z2 Β· u) = Pi_map_list (swap π”Έ z1 z2) (FV u).
-#z1 #z2 #u elim u //
-[ #s #v normalize //
-| #v1 #v2 normalize /2/ ]
-qed.
-
-lemma swap_inv_tm : βˆ€z1,z2,u.swap π”Έ z1 z2 Β· (swap π”Έ z1 z2 Β· u) = u.
-#z1 #z2 #u elim u [1,3,4:normalize //]
-#x whd in βŠ’ (??%?); >swap_inv %
-qed.
-
-lemma eqv_in_list : βˆ€x,l,z1,z2.x βˆˆ l β†’ swap π”Έ z1 z2 x βˆˆ Pi_map_list (swap π”Έ z1 z2) l.
-#x #l #z1 #z2 #Hin elim Hin
-[ #x0 #l0 %
-| #x1 #x2 #l0 #Hin #IH %2 @IH ]
-qed.
-
-lemma eqv_tm2 : βˆ€u.tm2 u β†’ βˆ€z1,z2.tm2 ((swap ? z1 z2)Β·u).
-#u #Hu #z1 #z2 letin p β‰ (swap ? z1 z2) elim Hu /2/
-#x #s #v #Hx #Hv #IH >pi_lam >pi_vopen_tm %3
-[ @(not_to_not β€¦ Hx) -Hx #Hx
-  <(swap_inv ? z1 z2 x) <(swap_inv_tm z1 z2 v) >eqv_FV @eqv_in_list //
-| #y #Hy <(swap_inv ? z1 z2 y)
-  <pi_vopen_tm @IH @(not_to_not β€¦ Hy) -Hy #Hy <(swap_inv ? z1 z2 y)
-  >eqv_FV @eqv_in_list //
-]
-qed.
-
-lemma vclose_vopen_aux : βˆ€x,u,k.vopen_tm_aux (vclose_tm_aux u x k) x k = u.
-#x #u elim u normalize //
-[ #n #k cases (true_or_false (leb k n)) #H >H whd in βŠ’ (??%?);
-  [ cases (true_or_false (eqb (S n) k)) #H1 >H1
-    [ <(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_true_to_le β€¦ H) -H #H
-      cases (le_to_not_lt β€¦ H) -H #H cases (H ?) %
-    | whd in βŠ’ (??%?); >lt_to_leb_false // @le_S_S /2/ ]
-  | cases (true_or_false (eqb n k)) #H1 >H1 normalize
-    [ >(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_false_to_not_le β€¦ H) -H
-      * #H cases (H ?) %
-    | >le_to_leb_true // @not_lt_to_le % #H2 >le_to_leb_true in H;
-      [ #H destruct (H) | /2/ ]
-    ]
-  ]
-| #x0 #k cases (true_or_false (x0==x)) #H1 >H1 normalize // >(\P H1) >eqb_n_n % ]
-qed.      
-
-lemma vclose_vopen : βˆ€x,u.((Ξ½x.u)⌈xβŒ‰) = u. #x #u @vclose_vopen_aux
-qed.
-
-(*
-theorem tm_to_tm : βˆ€t.tm' t β†’ tm t.
-#t #H elim H
-*)
-
-lemma in_list_singleton : βˆ€T.βˆ€t1,t2:T.t1 βˆˆ [t2] β†’ t1 = t2.
-#T #t1 #t2 #H @(in_list_inv_ind ??? H) /2/
-qed.
-
-lemma fresh_vclose_tm_aux : βˆ€u,x,k.x βˆ‰ FV (vclose_tm_aux u x k).
-#u #x elim u //
-[ #n #k normalize cases (leb k n) normalize //
-| #x0 #k normalize cases (true_or_false (x0==x)) #H >H normalize //
-  lapply (\Pf H) @not_to_not #Hin >(in_list_singleton ??? Hin) %
-| #v1 #v2 #IH1 #IH2 #k normalize % #Hin cases (in_list_append_to_or_in_list ???? Hin) /2/ ]
-qed.
-
-lemma fresh_vclose_tm : βˆ€u,x.x βˆ‰ FV (Ξ½x.u). //
-qed.
-
-lemma check_tm_true_to_toc : βˆ€u,k.check_tm u k = true β†’ tm_or_ctx k u.
-#u @(pretm_ind_plus ???? [ ] ? u)
-[ #x #k #_ %2
-| #n #k change with (leb (S n) k) in βŠ’ (??%?β†’?); #H % @leb_true_to_le //
-| #v1 #v2 #rv1 #rv2 #k change with (pretm_ind_plus ???????) in βŠ’ (??%?β†’?);
-  >pretm_ind_plus_app #H cases (andb_true ?? H) -H #Hv1 #Hv2 %3
-  [ @rv1 @Hv1 | @rv2 @Hv2 ]
-| #x #s #v #Hx #_ #rv #k change with (pretm_ind_plus ???????) in βŠ’ (??%?β†’?); 
-  >pretm_ind_plus_lam // #Hv %4 @rv @Hv ]
-qed.
-
-lemma toc_to_check_tm_true : βˆ€u,k.tm_or_ctx k u β†’ check_tm u k = true.
-#u #k #Hu elim Hu //
-[ #n #Hn change with (leb (S n) k) in βŠ’ (??%?); @le_to_leb_true @Hn
-| #v1 #v2 #Hv1 #Hv2 #IH1 #IH2 change with (pretm_ind_plus ???????) in βŠ’ (??%?);
-  >pretm_ind_plus_app change with (check_tm v1 k βˆ§ check_tm v2 k) in βŠ’ (??%?); /2/
-| #x #s #v #Hv #IH <(vclose_vopen x v) change with (pretm_ind_plus ???????) in βŠ’ (??%?);
-  >pretm_ind_plus_lam [| // | @fresh_vclose_tm ] >(vclose_vopen x v) @IH ]
-qed.
-
-lemma fresh_swap_tm : βˆ€z1,z2,u.z1 βˆ‰ FV u β†’ z2 βˆ‰ FV u β†’ swap π”Έ z1 z2 Β· u = u.
-#z1 #z2 #u elim u
-[2: normalize in βŠ’ (?β†’%β†’%β†’?); #x #Hz1 #Hz2 whd in βŠ’ (??%?); >swap_other //
-  [ @(not_to_not β€¦ Hz2) | @(not_to_not β€¦ Hz1) ] //
-|1: //
-| #s #v #IH normalize #Hz1 #Hz2 >IH // [@Hz2|@Hz1]
-| #v1 #v2 #IH1 #IH2 normalize #Hz1 #Hz2
-  >IH1 [| @(not_to_not β€¦ Hz2) @in_list_to_in_list_append_l | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_l ]
-  >IH2 // [@(not_to_not β€¦ Hz2) @in_list_to_in_list_append_r | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_r ]
-]
-qed.
-
-theorem tm_to_tm2 : βˆ€u.tm u β†’ tm2 u.
-#t #Ht elim Ht
-[ #n #Hn cases (not_le_Sn_O n) #Hfalse cases (Hfalse Hn)
-| @tm_par
-| #u #v #Hu #Hv @tm_app
-| #x #s #u #Hu #IHu <(vclose_vopen x u) @tm_lam
-  [ @fresh_vclose_tm
-  | #y #Hy <(fresh_swap_tm x y (Ξ½x.u)) /2/ @fresh_vclose_tm ]
-]
-qed.
-
-theorem tm2_to_tm : βˆ€u.tm2 u β†’ tm u.
-#u #pu elim pu /2/ #x #s #v #Hx #Hv #IH %4 @IH //
-qed.
-
-(* define PAR APP LAM *)
-definition PAR β‰ Ξ»x.mk_TM (par x) ?. // qed.
-definition APP β‰ Ξ»u,v:TM.mk_TM (app u v) ?.
-change with (pretm_ind_plus ???????) in match (check_tm ??); >pretm_ind_plus_app
-change with (check_tm ??) in match (pretm_ind_plus ???????); change with (check_tm ??) in match (pretm_ind_plus ???????) in βŠ’ (??(??%)?);
-@andb_elim >(tm_of_TM u) >(tm_of_TM v) % qed.
-definition LAM β‰ Ξ»x,s.Ξ»u:TM.mk_TM (lam x s u) ?.
-change with (pretm_ind_plus ???????) in match (check_tm ??); <(vclose_vopen x u)
->pretm_ind_plus_lam [| // | @fresh_vclose_tm ]
-change with (check_tm ??) in match (pretm_ind_plus ???????); >vclose_vopen
-@(tm_of_TM u) qed.
-
-axiom vopen_tm_down : βˆ€u,x,k.tm_or_ctx (S k) u β†’ tm_or_ctx k (u⌈xβŒ‰).
-(* needs true_plus_false
-
-#u #x #k #Hu elim Hu
-[ #n #Hn normalize cases (true_or_false (eqb n O)) #H >H [%2]
-  normalize >(?: leb n O = false) [|cases n in H; // >eqb_n_n #H destruct (H) ]
-  normalize lapply Hn cases n in H; normalize [ #Hfalse destruct (Hfalse) ]
-  #n0 #_ #Hn0 % @le_S_S_to_le //
-| #x0 %2
-| #v1 #v2 #Hv1 #Hv2 #IH1 #IH2 %3 //
-| #x0 #s #v #Hv #IH normalize @daemon
-]
-qed.
-*)
-
-definition vopen_TM β‰ Ξ»u:CTX.Ξ»x.mk_TM (u⌈xβŒ‰) ?.
-@toc_to_check_tm_true @vopen_tm_down @check_tm_true_to_toc @ctx_of_CTX qed.
-
-axiom vclose_tm_up : βˆ€u,x,k.tm_or_ctx k u β†’ tm_or_ctx (S k) (Ξ½x.u).
-
-definition vclose_TM β‰ Ξ»u:TM.Ξ»x.mk_CTX (Ξ½x.u) ?. 
-@toc_to_check_tm_true @vclose_tm_up @check_tm_true_to_toc @tm_of_TM qed.
-
-interpretation "ln wf term variable open" 'open u x = (vopen_TM u x).
-interpretation "ln wf term variable close" 'nu x u = (vclose_TM u x).
-
-theorem tm_alpha : βˆ€x,y,s,u.x βˆ‰ FV u β†’ y βˆ‰ FV u β†’ lam x s (u⌈xβŒ‰) = lam y s (u⌈yβŒ‰).
-#x #y #s #u #Hx #Hy whd in βŠ’ (??%%); @eq_f >nominal_eta // >nominal_eta //
-qed.
-
-lemma TM_to_tm2 : βˆ€u:TM.tm2 u.
-#u @tm_to_tm2 @check_tm_true_to_toc @tm_of_TM qed.
-
-theorem TM_ind_plus_weak : 
- βˆ€P:pretm β†’ Type[0].
-   (βˆ€x:𝔸.P (PAR x)) β†’ 
-   (βˆ€v1,v2:TM.P v1 β†’ P v2 β†’ P (APP v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s.βˆ€v:CTX.x βˆ‰ FV v β†’ x βˆ‰ C β†’ 
-     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (LAM x s (v⌈xβŒ‰))) β†’
- βˆ€u:TM.P u.
-#P #Hpar #Happ #C #Hlam #u elim (TM_to_tm2 u) //
-[ #v1 #v2 #pv1 #pv2 #IH1 #IH2 @(Happ (mk_TM β€¦) (mk_TM β€¦) IH1 IH2)
-  @toc_to_check_tm_true @tm2_to_tm //
-| #x #s #v #Hx #pv #IH
-  lapply (p_fresh β€¦ (C@FV v)) letin x0 β‰ (N_fresh β€¦ (C@FV v)) #Hx0
-  >(?:lam x s (v⌈xβŒ‰) = lam x0 s (v⌈x0βŒ‰))
-  [|@tm_alpha // @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r ]
-  @(Hlam x0 s (mk_CTX v ?) ??)
-  [ <(nominal_eta β€¦ Hx) @toc_to_check_tm_true @vclose_tm_up @tm2_to_tm @pv //
-  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r
-  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_l
-  | @IH ]
-]
-qed.
-
-lemma eq_mk_TM : βˆ€u,v.u = v β†’ βˆ€pu,pv.mk_TM u pu = mk_TM v pv.
-#u #v #Heq >Heq #pu #pv %
-qed.
-
-lemma eq_P : βˆ€T:Type[0].βˆ€t1,t2:T.t1 = t2 β†’ βˆ€P:T β†’ Type[0].P t1 β†’ P t2. // qed.
-
-theorem TM_ind_plus :
- βˆ€P:TM β†’ Type[0].
-   (βˆ€x:𝔸.P (PAR x)) β†’ 
-   (βˆ€v1,v2:TM.P v1 β†’ P v2 β†’ P (APP v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s.βˆ€v:CTX.x βˆ‰ FV v β†’ x βˆ‰ C β†’ 
-     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (LAM x s (v⌈xβŒ‰))) β†’
- βˆ€u:TM.P u.
-#P #Hpar #Happ #C #Hlam * #u #pu
->(?:mk_TM u pu = 
-    mk_TM u (toc_to_check_tm_true β€¦ (tm2_to_tm β€¦ (tm_to_tm2 β€¦ (check_tm_true_to_toc β€¦ pu))))) [|%]
-elim (tm_to_tm2 u ?) //
-[ #v1 #v2 #pv1 #pv2 #IH1 #IH2 @(Happ (mk_TM β€¦) (mk_TM β€¦) IH1 IH2)
-| #x #s #v #Hx #pv #IH
-  lapply (p_fresh β€¦ (C@FV v)) letin x0 β‰ (N_fresh β€¦ (C@FV v)) #Hx0
-  lapply (Hlam x0 s (mk_CTX v ?) ???) 
-  [2: @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_l @Hx0
-  |4: @toc_to_check_tm_true <(nominal_eta x v) // @vclose_tm_up @tm2_to_tm @pv // 
-  | #y #Hy whd in match (vopen_TM ??);
-    >(?:mk_TM (v⌈yβŒ‰) ? = mk_TM (v⌈yβŒ‰) (toc_to_check_tm_true (v⌈yβŒ‰) O (tm2_to_tm (v⌈yβŒ‰) (pv y Hy))))
-    [@IH|%]
-  | @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_r @Hx0 
-  | @eq_P @eq_mk_TM whd in match (vopen_TM ??); @tm_alpha // @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r ]
-]
-qed.
-
-notation 
-"hvbox('nominal' u 'return' out 'with' 
-       [ 'xpar' ident x β‡’ f1 
-       | 'xapp' ident v1 ident v2 ident recv1 ident recv2 β‡’ f2 
-       | 'xlam' β¨ident y # C❩ ident s ident w ident py1 ident py2 ident recw β‡’ f3 ])"
-with precedence 48 
-for @{ TM_ind_plus $out (Ξ»${ident x}:?.$f1)
-       (Ξ»${ident v1}:?.Ξ»${ident v2}:?.Ξ»${ident recv1}:?.Ξ»${ident recv2}:?.$f2)
-       $C (Ξ»${ident y}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.Ξ»${ident recw}:?.$f3)
-       $u }.
-       
-(* include "basics/jmeq.ma".*)
-
-definition subst β‰ (Ξ»u:TM.Ξ»x,v.
-  nominal u return (Ξ»_.TM) with 
-  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ PAR x0 ]  (* u instead of PAR x0 does not work, u stays the same at every rec call! *)
-  | xapp v1 v2 recv1 recv2 β‡’ APP recv1 recv2
-  | xlam β¨y # x::FV v❩ s w py1 py2 recw β‡’ LAM y s (recw y py1) ]).
-  
-lemma subst_def : βˆ€u,x,v.subst u x v =
-  nominal u return (Ξ»_.TM) with 
-  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ PAR x0 ]
-  | xapp v1 v2 recv1 recv2 β‡’ APP recv1 recv2
-  | xlam β¨y # x::FV v❩ s w py1 py2 recw β‡’ LAM y s (recw y py1) ]. //
-qed.
-
-axiom TM_ind_plus_LAM : 
-  βˆ€x,s,u,out,f1,f2,C,f3,Hx1,Hx2.
-  TM_ind_plus out f1 f2 C f3 (LAM x s (u⌈xβŒ‰)) = 
-  f3 x s u Hx1 Hx2 (Ξ»y,Hy.TM_ind_plus ? f1 f2 C f3 ?).
-  
-axiom TM_ind_plus_APP : 
-  βˆ€u1,u2,out,f1,f2,C,f3.
-  TM_ind_plus out f1 f2 C f3 (APP u1 u2) = 
-  f2 u1 u2 (TM_ind_plus out f1 f2 C f3 ?) (TM_ind_plus out f1 f2 C f3 ?).
-  
-lemma eq_mk_CTX : βˆ€u,v.u = v β†’ βˆ€pu,pv.mk_CTX u pu = mk_CTX v pv.
-#u #v #Heq >Heq #pu #pv %
-qed.
-
-lemma vclose_vopen_TM : βˆ€x.βˆ€u:TM.((Ξ½x.u)⌈xβŒ‰) = u.
-#x * #u #pu @eq_mk_TM @vclose_vopen qed.
-
-lemma nominal_eta_CTX : βˆ€x.βˆ€u:CTX.x βˆ‰ FV u β†’ (Ξ½x.(u⌈xβŒ‰)) = u.
-#x * #u #pu #Hx @eq_mk_CTX @nominal_eta // qed. 
-
-theorem TM_alpha : βˆ€x,y,s.βˆ€u:CTX.x βˆ‰ FV u β†’ y βˆ‰ FV u β†’ LAM x s (u⌈xβŒ‰) = LAM y s (u⌈yβŒ‰).
-#x #y #s #u #Hx #Hy @eq_mk_TM @tm_alpha // qed.
-
-axiom in_vopen_CTX : βˆ€x,y.βˆ€v:CTX.x βˆˆ FV (v⌈yβŒ‰) β†’ x = y βˆ¨ x βˆˆ FV v.
-
-theorem subst_fresh : βˆ€u,v:TM.βˆ€x.x βˆ‰ FV u β†’ subst u x v = u.
-#u #v #x @(TM_ind_plus β€¦ (x::FV v) β€¦ u)
-[ #x0 normalize in βŠ’ (%β†’?); #Hx normalize in βŠ’ (??%?);
-  >(\bf ?) [| @(not_to_not β€¦ Hx) #Heq >Heq % ] %
-| #u1 #u2 #IH1 #IH2 normalize in βŠ’ (%β†’?); #Hx
-  >subst_def >TM_ind_plus_APP @eq_mk_TM @eq_f2 @eq_f
-  [ <subst_def @IH1 @(not_to_not β€¦ Hx) @in_list_to_in_list_append_l
-  | <subst_def @IH2 @(not_to_not β€¦ Hx) @in_list_to_in_list_append_r ]
-| #x0 #s #v0 #Hx0 #HC #IH #Hx >subst_def >TM_ind_plus_LAM [|@HC|@Hx0]
-  @eq_f <subst_def @IH // @(not_to_not β€¦ Hx) -Hx #Hx
-  change with (FV (Ξ½x0.(v0⌈x0βŒ‰))) in βŠ’ (???%); >nominal_eta_CTX //
-  cases (in_vopen_CTX β€¦ Hx) // #Heq >Heq in HC; * #HC @False_ind @HC %
-]
-qed.
-
-example subst_LAM_same : βˆ€x,s,u,v. subst (LAM x s u) x v = LAM x s u.
-#x #s #u #v >subst_def <(vclose_vopen_TM x u)
-lapply (p_fresh β€¦ (FV (Ξ½x.u)@x::FV v)) letin x0 β‰ (N_fresh β€¦ (FV (Ξ½x.u)@x::FV v)) #Hx0
->(TM_alpha x x0)
-[| @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_l @Hx0 | @fresh_vclose_tm ]
->TM_ind_plus_LAM [| @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_r @Hx0 | @(not_to_not β€¦ Hx0) -Hx0 #Hx0 @in_list_to_in_list_append_l @Hx0 ]
-@eq_f change with (subst ((Ξ½x.u)⌈x0βŒ‰) x v) in βŠ’ (??%?); @subst_fresh
-@(not_to_not β€¦ Hx0) #Hx0' cases (in_vopen_CTX β€¦ Hx0') 
-[ #Heq >Heq @in_list_to_in_list_append_r %
-| #Hfalse @False_ind cases (fresh_vclose_tm u x) #H @H @Hfalse ]
-qed.
-
-(*
-notation > "Ξ› ident x. ident T [ident x] β†¦ P"
-  with precedence 48 for @{'foo (Ξ»${ident x}.Ξ»${ident T}.$P)}.
-
-notation < "Ξ› ident x. ident T [ident x] β†¦ P"
-  with precedence 48 for @{'foo (Ξ»${ident x}:$Q.Ξ»${ident T}:$R.$P)}.
-*)
-
-(*
-notation 
-"hvbox('nominal' u 'with' 
-       [ 'xpar' ident x β‡’ f1 
-       | 'xapp' ident v1 ident v2  β‡’ f2
-       | 'xlam' ident x # C s w β‡’ f3 ])"
-with precedence 48 
-for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
- (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
- $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
-*)
-
-(*
-notation 
-"hvbox('nominal' u 'with' 
-       [ 'xpar' ident x ^ f1 
-       | 'xapp' ident v1 ident v2 ^ f2 ])"
-(*       | 'xlam' ident x # C s w ^ f3 ]) *)
-with precedence 48 
-for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
- (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
- $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
-*)
-notation 
-"hvbox('nominal' u 'with' 
-       [ 'xpar' ident x ^ f1 
-       | 'xapp' ident v1 ident v2 ^ f2 ])"
-with precedence 48 
-for @{ tm2_ind_plus ? (Ξ»${ident x}:?.$f1) 
- (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
- $C (Ξ»${ident x}:?.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
-
-axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
-notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
-interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
-
-
-
-inductive judg : list tp β†’ tm β†’ tp β†’ Prop β‰ 
-| t_var : βˆ€g,n,t.Nth ? n g = Some ? t β†’ judg g (var n) t
-| t_app : βˆ€g,m,n,t,u.judg g m (arr t u) β†’ judg g n t β†’ judg g (app m n) u
-| t_abs : βˆ€g,t,m,u.judg (t::g) m u β†’ judg g (abs t m) (arr t u).
-
-definition Env := list (𝔸 Γ— tp).
-
-axiom vclose_env : Env β†’ list tp.
-axiom vclose_tm : Env β†’ tm β†’ tm.
-axiom Lam : π”Έ β†’ tp β†’ tm β†’ tm.
-definition Judg β‰ Ξ»G,M,T.judg (vclose_env G) (vclose_tm G M) T.
-definition dom β‰ Ξ»G:Env.map ?? (fst ??) G.
-
-definition sctx β‰ π”Έ Γ— tm.
-axiom swap_tm : π”Έ β†’ π”Έ β†’ tm β†’ tm.
-definition sctx_app : sctx β†’ π”Έ β†’ tm β‰ Ξ»M0,Y.let βŒ©X,MβŒͺ β‰ M0 in swap_tm X Y M.
-
-axiom in_list : βˆ€A:Type[0].A β†’ list A β†’ Prop.
-interpretation "list membership" 'mem x l = (in_list ? x l).
-interpretation "list non-membership" 'notmem x l = (Not (in_list ? x l)).
-
-axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
-notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
-interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
-
-(* axiom Lookup : π”Έ β†’ Env β†’ option tp. *)
-
-(* forma alto livello del judgment
-   t_abs* : βˆ€G,T,X,M,U.
-            (βˆ€Y βˆ‰ supp(M).Judg (〈Y,TβŒͺ::G) (M[Y]) U) β†’ 
-            Judg G (Lam X T (M[X])) (arr T U) *)
-
-(* prima dimostrare, poi perfezionare gli assiomi, poi dimostrarli *)
-
-axiom Judg_ind : βˆ€P:Env β†’ tm β†’ tp β†’ Prop.
-  (βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ P G (par X) T) β†’ 
-  (βˆ€G,M,N,T,U.
-    Judg G M (arr T U) β†’ Judg G N T β†’ 
-    P G M (arr T U) β†’ P G N T β†’ P G (app M N) U) β†’ 
-  (βˆ€G,T1,T2,X,M1.
-    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ Judg (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’
-    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ P (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’ 
-    P G (Lam X T1 (sctx_app M1 X)) (arr T1 T2)) β†’ 
-  βˆ€G,M,T.Judg G M T β†’ P G M T.
-
-axiom t_par : βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ Judg G (par X) T.
-axiom t_app2 : βˆ€G,M,N,T,U.Judg G M (arr T U) β†’ Judg G N T β†’ Judg G (app M N) U.
-axiom t_Lam : βˆ€G,X,M,T,U.Judg (〈X,TβŒͺ::G) M U β†’ Judg G (Lam X T M) (arr T U).
-
-definition subenv β‰ Ξ»G1,G2.βˆ€x.x β—ƒ G1 β†’ x β—ƒ G2.
-interpretation "subenv" 'subseteq G1 G2 = (subenv G1 G2).
-
-axiom daemon : βˆ€P:Prop.P.
-
-theorem weakening : βˆ€G1,G2,M,T.G1 βŠ† G2 β†’ Judg G1 M T β†’ Judg G2 M T.
-#G1 #G2 #M #T #Hsub #HJ lapply Hsub lapply G2 -G2 change with (βˆ€G2.?)
-@(Judg_ind β€¦ HJ)
-[ #X #G #T0 #Hin #G2 #Hsub @t_par @Hsub //
-| #G #M0 #N #T0 #U #HM0 #HN #IH1 #IH2 #G2 #Hsub @t_app2
-  [| @IH1 // | @IH2 // ]
-| #G #T1 #T2 #X #M1 #HM1 #IH #G2 #Hsub @t_Lam @IH 
-  [ (* trivial property of Lam *) @daemon 
-  | (* trivial property of subenv *) @daemon ]
-]
-qed.
-
-(* Serve un tipo Tm per i termini localmente chiusi e i suoi principi di induzione e
-   ricorsione *)
\ No newline at end of file
diff --git a/matita/matita/lib/binding/ln_concrete.ma b/matita/matita/lib/binding/ln_concrete.ma
deleted file mode 100644 (file)
index bdafdb1..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-(**************************************************************************)
-(*       ___                                                              *)
-(*      ||M||                                                             *)
-(*      ||A||       A project by Andrea Asperti                           *)
-(*      ||T||                                                             *)
-(*      ||I||       Developers:                                           *)
-(*      ||T||         The HELM team.                                      *)
-(*      ||A||         http://helm.cs.unibo.it                             *)
-(*      \   /                                                             *)
-(*       \ /        This file is distributed under the terms of the       *)
-(*        v         GNU General Public License Version 2                  *)
-(*                                                                        *)
-(**************************************************************************)
-
-include "basics/lists/list.ma".
-include "basics/deqsets.ma".
-include "binding/names.ma".
-include "binding/fp.ma".
-
-definition alpha : Nset β‰ X. check alpha
-notation "𝔸" non associative with precedence 90 for @{'alphabet}.
-interpretation "set of names" 'alphabet = alpha.
-
-inductive tp : Type[0] β‰ 
-| top : tp
-| arr : tp β†’ tp β†’ tp.
-inductive pretm : Type[0] β‰ 
-| var : nat β†’ pretm
-| par :  π”Έ β†’ pretm
-| abs : tp β†’ pretm β†’ pretm
-| app : pretm β†’ pretm β†’ pretm.
-
-let rec Nth T n (l:list T) on n β‰ 
-  match l with 
-  [ nil β‡’ None ?
-  | cons hd tl β‡’ match n with
-    [ O β‡’ Some ? hd
-    | S n0 β‡’ Nth T n0 tl ] ].
-
-let rec vclose_tm_aux u x k β‰ match u with
-  [ var n β‡’ if (leb k n) then var (S n) else u
-  | par x0 β‡’ if (x0 == x) then (var k) else u
-  | app v1 v2 β‡’ app (vclose_tm_aux v1 x k) (vclose_tm_aux v2 x k)
-  | abs s v β‡’ abs s (vclose_tm_aux v x (S k)) ].
-definition vclose_tm β‰ Ξ»u,x.vclose_tm_aux u x O.  
-
-definition vopen_var β‰ Ξ»n,x,k.match eqb n k with
- [ true β‡’ par x
- | false β‡’ match leb n k with
-   [ true β‡’ var n
-   | false β‡’ var (pred n) ] ].
-
-let rec vopen_tm_aux u x k β‰ match u with
-  [ var n β‡’ vopen_var n x k
-  | par x0 β‡’ u
-  | app v1 v2 β‡’ app (vopen_tm_aux v1 x k) (vopen_tm_aux v2 x k)
-  | abs s v β‡’ abs s (vopen_tm_aux v x (S k)) ].
-definition vopen_tm β‰ Ξ»u,x.vopen_tm_aux u x O.
-
-let rec FV u β‰ match u with 
-  [ par x β‡’ [x]
-  | app v1 v2 β‡’ FV v1@FV v2
-  | abs s v β‡’ FV v
-  | _ β‡’ [ ] ].  
-
-definition lam β‰ Ξ»x,s,u.abs s (vclose_tm u x).
-
-let rec Pi_map_tm p u on u β‰ match u with
-[ par x β‡’ par (p x)
-| var _ β‡’ u
-| app v1 v2 β‡’ app (Pi_map_tm p v1) (Pi_map_tm p v2)
-| abs s v β‡’ abs s (Pi_map_tm p v) ].
-
-interpretation "permutation of tm" 'middot p x = (Pi_map_tm p x).
-
-notation "hvbox(u⌈xβŒ‰)"
-  with precedence 45
-  for @{ 'open $u $x }.
-
-(*
-notation "hvbox(u⌈xβŒ‰)"
-  with precedence 45
-  for @{ 'open $u $x }.
-notation "❴ u β΅ x" non associative with precedence 90 for @{ 'open $u $x }.
-*)
-interpretation "ln term variable open" 'open u x = (vopen_tm u x).
-notation < "hvbox(Ξ½ x break . u)"
- with precedence 20
-for @{'nu $x $u }.
-notation > "Ξ½ list1 x sep , . term 19 u" with precedence 20
-  for ${ fold right @{$u} rec acc @{'nu $x $acc)} }.
-interpretation "ln term variable close" 'nu x u = (vclose_tm u x).
-
-let rec tm_height u β‰ match u with
-[ app v1 v2 β‡’ S (max (tm_height v1) (tm_height v2))
-| abs s v β‡’ S (tm_height v) 
-| _ β‡’ O ].
-
-theorem le_n_O_rect_Type0 : βˆ€n:nat. n β‰€ O β†’ βˆ€P: nat β†’Type[0]. P O β†’ P n.
-#n (cases n) // #a #abs cases (?:False) /2/ qed. 
-
-theorem nat_rect_Type0_1 : βˆ€n:nat.βˆ€P:nat β†’ Type[0]. 
-(βˆ€m.(βˆ€p. p < m β†’ P p) β†’ P m) β†’ P n.
-#n #P #H 
-cut (βˆ€q:nat. q β‰€ n β†’ P q) /2/
-(elim n) 
- [#q #HleO (* applica male *) 
-    @(le_n_O_rect_Type0 ? HleO)
-    @H #p #ltpO cases (?:False) /2/ (* 3 *)
- |#p #Hind #q #HleS 
-    @H #a #lta @Hind @le_S_S_to_le /2/
- ]
-qed.
-
-lemma leb_false_to_lt : βˆ€n,m. leb n m = false β†’ m < n.
-#n elim n
-[ #m normalize #H destruct(H)
-| #n0 #IH * // #m normalize #H @le_S_S @IH // ]
-qed.
-
-lemma nominal_eta_aux : βˆ€x,u.x βˆ‰ FV u β†’ βˆ€k.vclose_tm_aux (vopen_tm_aux u x k) x k = u.
-#x #u elim u
-[ #n #_ #k normalize cases (decidable_eq_nat n k) #Hnk
-  [ >Hnk >eqb_n_n whd in βŠ’ (??%?); >(\b ?) //
-  | >(not_eq_to_eqb_false β€¦ Hnk) normalize cases (true_or_false (leb n k)) #Hleb
-    [ >Hleb normalize >(?:leb k n = false) //
-      @lt_to_leb_false @not_eq_to_le_to_lt /2/
-    | >Hleb normalize >(?:leb k (pred n) = true) normalize
-      [ cases (leb_false_to_lt β€¦ Hleb) //
-      | @le_to_leb_true cases (leb_false_to_lt β€¦ Hleb) normalize /2/ ] ] ]
-| #y normalize in βŠ’ (%β†’?β†’?); #Hy whd in βŠ’ (?β†’??%?); >(\bf ?) // @(not_to_not β€¦ Hy) //
-| #s #v #IH normalize #Hv #k >IH // @Hv
-| #v1 #v2 #IH1 #IH2 normalize #Hv1v2 #k 
-  >IH1 [ >IH2 // | @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_l ]
-  @(not_to_not β€¦ Hv1v2) @in_list_to_in_list_append_r ]
-qed.
-
-corollary nominal_eta : βˆ€x,u.x βˆ‰ FV u β†’ (Ξ½x.u⌈xβŒ‰) = u.
-#x #u #Hu @nominal_eta_aux //
-qed.
-
-lemma eq_height_vopen_aux : βˆ€v,x,k.tm_height (vopen_tm_aux v x k) = tm_height v.
-#v #x elim v
-[ #n #k normalize cases (eqb n k) // cases (leb n k) //
-| #u #k %
-| #s #u #IH #k normalize >IH %
-| #u1 #u2 #IH1 #IH2 #k normalize >IH1 >IH2 % ]
-qed.
-
-corollary eq_height_vopen : βˆ€v,x.tm_height (v⌈xβŒ‰) = tm_height v.
-#v #x @eq_height_vopen_aux
-qed.
-
-theorem pretm_ind_plus_aux : 
- βˆ€P:pretm β†’ Type[0].
-   (βˆ€x:𝔸.P (par x)) β†’ 
-   (βˆ€n:β„•.P (var n)) β†’ 
-   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
- βˆ€n,u.tm_height u β‰€ n β†’ P u.
-#P #Hpar #Hvar #Happ #C #Hlam #n change with ((Ξ»n.?) n); @(nat_rect_Type0_1 n ??)
-#m cases m
-[ #_ * /2/
-  [ normalize #s #v #Hfalse cases (?:False) cases (not_le_Sn_O (tm_height v)) /2/
-  | #v1 #v2 whd in βŠ’ (?%?β†’?); #Hfalse cases (?:False) cases (not_le_Sn_O (S (max ??))) /2/ ] ]
--m #m #IH * /2/
-[ #s #v whd in βŠ’ (?%?β†’?); #Hv
-  lapply (p_fresh β€¦ (C@FV v)) letin y β‰ (N_fresh β€¦ (C@FV v)) #Hy
-  >(?:abs s v = lam y s (v⌈yβŒ‰))
-  [| whd in βŠ’ (???%); >nominal_eta // @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r ] 
-  @Hlam
-  [ @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r
-  | @(not_to_not β€¦ Hy) @in_list_to_in_list_append_l ]
-  @IH [| @Hv | >eq_height_vopen % ]
-| #v1 #v2 whd in βŠ’ (?%?β†’?); #Hv @Happ
-  [ @IH [| @Hv | // ] | @IH [| @Hv | // ] ] ]
-qed.
-
-corollary pretm_ind_plus :
- βˆ€P:pretm β†’ Type[0].
-   (βˆ€x:𝔸.P (par x)) β†’ 
-   (βˆ€n:β„•.P (var n)) β†’ 
-   (βˆ€v1,v2. P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ P (v⌈xβŒ‰) β†’ P (lam x s (v⌈xβŒ‰))) β†’
- βˆ€u.P u.
-#P #Hpar #Hvar #Happ #C #Hlam #u @pretm_ind_plus_aux /2/
-qed.
-
-(* maps a permutation to a list of terms *)
-definition Pi_map_list : (𝔸 β†’ π”Έ) β†’ list π”Έ β†’ list π”Έ β‰ map π”Έ π”Έ .
-
-(* interpretation "permutation of name list" 'middot p x = (Pi_map_list p x).*)
-
-(*
-inductive tm : pretm β†’ Prop β‰ 
-| tm_par : βˆ€x:𝔸.tm (par x)
-| tm_app : βˆ€u,v.tm u β†’ tm v β†’ tm (app u v)
-| tm_lam : βˆ€x,s,u.tm u β†’ tm (lam x s u).
-
-inductive ctx_aux : nat β†’ pretm β†’ Prop β‰ 
-| ctx_var : βˆ€n,k.n < k β†’ ctx_aux k (var n)
-| ctx_par : βˆ€x,k.ctx_aux k (par x)
-| ctx_app : βˆ€u,v,k.ctx_aux k u β†’ ctx_aux k v β†’ ctx_aux k (app u v)
-(* Γ¨ sostituibile da ctx_lam ? *)
-| ctx_abs : βˆ€s,u.ctx_aux (S k) u β†’ ctx_aux k (abs s u).
-*)
-
-inductive tm_or_ctx (k:nat) : pretm β†’ Type[0] β‰ 
-| toc_var : βˆ€n.n < k β†’ tm_or_ctx k (var n)
-| toc_par : βˆ€x.tm_or_ctx k (par x)
-| toc_app : βˆ€u,v.tm_or_ctx k u β†’ tm_or_ctx k v β†’ tm_or_ctx k (app u v)
-| toc_lam : βˆ€x,s,u.tm_or_ctx k u β†’ tm_or_ctx k (lam x s u).
-
-definition tm β‰ Ξ»t.tm_or_ctx O t.
-definition ctx β‰ Ξ»t.tm_or_ctx 1 t.
-
-record TM : Type[0] β‰ {
-  pretm_of_TM :> pretm;
-  tm_of_TM : tm pretm_of_TM
-}.
-
-record CTX : Type[0] β‰ {
-  pretm_of_CTX :> pretm;
-  ctx_of_CTX : ctx pretm_of_CTX
-}.
-
-inductive tm2 : pretm β†’ Type[0] β‰ 
-| tm_par : βˆ€x.tm2 (par x)
-| tm_app : βˆ€u,v.tm2 u β†’ tm2 v β†’ tm2 (app u v)
-| tm_lam : βˆ€x,s,u.x βˆ‰ FV u β†’ (βˆ€y.y βˆ‰ FV u β†’ tm2 (u⌈yβŒ‰)) β†’ tm2 (lam x s (u⌈xβŒ‰)).
-
-(*
-inductive tm' : pretm β†’ Prop β‰ 
-| tm_par : βˆ€x.tm' (par x)
-| tm_app : βˆ€u,v.tm' u β†’ tm' v β†’ tm' (app u v)
-| tm_lam : βˆ€x,s,u,C.x βˆ‰ FV u β†’ x βˆ‰ C β†’ (βˆ€y.y βˆ‰ FV u β†’ tm' (❴u❡y)) β†’ tm' (lam x s (❴u❡x)).
-*)
-
-axiom swap_inj : βˆ€N.βˆ€z1,z2,x,y.swap N z1 z2 x = swap N z1 z2 y β†’ x = y.
-
-lemma pi_vclose_tm : 
-  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(Ξ½x.u) = (Ξ½ swap ? z1 z2 x.swap π”Έ z1 z2 Β· u).
-#z1 #z2 #x #u
-change with (vclose_tm_aux ???) in match (vclose_tm ??);
-change with (vclose_tm_aux ???) in βŠ’ (???%); lapply O elim u
-[3:whd in βŠ’ (?β†’?β†’(?β†’ ??%%)β†’?β†’??%%); //
-|4:whd in βŠ’ (?β†’?β†’(?β†’??%%)β†’(?β†’??%%)β†’?β†’??%%); //
-| #n #k whd in βŠ’ (??(??%)%); cases (leb k n) normalize %
-| #x0 #k cases (true_or_false (x0==z1)) #H1 >H1 whd in βŠ’ (??%%);
-  [ cases (true_or_false (x0==x)) #H2 >H2 whd in βŠ’ (??(??%)%);
-    [ <(\P H2) >H1 whd in βŠ’ (??(??%)%); >(\b ?) // >(\b ?) //
-    | >H2 whd in match (swap ????); >H1
-      whd in match (if false then var k else ?);
-      whd in match (if true then z2 else ?); >(\bf ?)
-      [ >(\P H1) >swap_left %
-      | <(swap_inv ? z1 z2 z2) in βŠ’ (?(??%?)); % #H3
-        lapply (swap_inj β€¦ H3) >swap_right #H4 <H4 in H2; >H1 #H destruct (H) ]
-    ]
-  | >(?:(swap ? z1 z2 x0 == swap ? z1 z2 x) = (x0 == x))
-    [| cases (true_or_false (x0==x)) #H2 >H2
-      [ >(\P H2) @(\b ?) %
-      | @(\bf ?) % #H >(swap_inj β€¦ H) in H2; >(\b ?) // #H0 destruct (H0) ] ]
-    cases (true_or_false (x0==x)) #H2 >H2 whd in βŠ’ (??(??%)%); 
-    [ <(\P H2) >H1 >(\b (refl ??)) %
-    | >H1 >H2 % ]
-    ]
-  ]
-qed.
-
-lemma pi_vopen_tm : 
-  βˆ€z1,z2,x,u.swap π”Έ z1 z2Β·(u⌈xβŒ‰) = (swap π”Έ z1 z2 Β· u⌈swap π”Έ z1 z2 xβŒ‰).
-#z1 #z2 #x #u
-change with (vopen_tm_aux ???) in match (vopen_tm ??);
-change with (vopen_tm_aux ???) in βŠ’ (???%); lapply O elim u //
-[2: #s #v whd in βŠ’ ((?β†’??%%)β†’?β†’??%%); //
-|3: #v1 #v2 whd in βŠ’ ((?β†’??%%)β†’(?β†’??%%)β†’?β†’??%%); /2/ ]
-#n #k whd in βŠ’ (??(??%)%); cases (true_or_false (eqb n k)) #H1 >H1 //
-cases (true_or_false (leb n k)) #H2 >H2 normalize //
-qed.
-
-lemma pi_lam : 
-  βˆ€z1,z2,x,s,u.swap π”Έ z1 z2 Β· lam x s u = lam (swap π”Έ z1 z2 x) s (swap π”Έ z1 z2 Β· u).
-#z1 #z2 #x #s #u whd in βŠ’ (???%); <(pi_vclose_tm β€¦) %
-qed.
-
-lemma eqv_FV : βˆ€z1,z2,u.FV (swap π”Έ z1 z2 Β· u) = Pi_map_list (swap π”Έ z1 z2) (FV u).
-#z1 #z2 #u elim u //
-[ #s #v #H @H
-| #v1 #v2 whd in βŠ’ (??%%β†’??%%β†’??%%); #H1 #H2 >H1 >H2
-  whd in βŠ’ (???(????%)); /2/ ]
-qed.
-
-lemma swap_inv_tm : βˆ€z1,z2,u.swap π”Έ z1 z2 Β· (swap π”Έ z1 z2 Β· u) = u.
-#z1 #z2 #u elim u 
-[1: #n %
-|3: #s #v whd in βŠ’ (?β†’??%%); //
-|4: #v1 #v2 #Hv1 #Hv2 whd in βŠ’ (??%%); // ]
-#x whd in βŠ’ (??%?); >swap_inv %
-qed.
-
-lemma eqv_in_list : βˆ€x,l,z1,z2.x βˆˆ l β†’ swap π”Έ z1 z2 x βˆˆ Pi_map_list (swap π”Έ z1 z2) l.
-#x #l #z1 #z2 #Hin elim Hin
-[ #x0 #l0 %
-| #x1 #x2 #l0 #Hin #IH %2 @IH ]
-qed.
-
-lemma eqv_tm2 : βˆ€u.tm2 u β†’ βˆ€z1,z2.tm2 ((swap ? z1 z2)Β·u).
-#u #Hu #z1 #z2 letin p β‰ (swap ? z1 z2) elim Hu /2/
-#x #s #v #Hx #Hv #IH >pi_lam >pi_vopen_tm %3
-[ @(not_to_not β€¦ Hx) -Hx #Hx
-  <(swap_inv ? z1 z2 x) <(swap_inv_tm z1 z2 v) >eqv_FV @eqv_in_list //
-| #y #Hy <(swap_inv ? z1 z2 y)
-  <pi_vopen_tm @IH @(not_to_not β€¦ Hy) -Hy #Hy <(swap_inv ? z1 z2 y)
-  >eqv_FV @eqv_in_list //
-]
-qed.
-
-lemma vclose_vopen_aux : βˆ€x,u,k.vopen_tm_aux (vclose_tm_aux u x k) x k = u.
-#x #u elim u [1,3,4:normalize //]
-[ #n #k cases (true_or_false (leb k n)) #H >H whd in βŠ’ (??%?);
-  [ cases (true_or_false (eqb (S n) k)) #H1 >H1
-    [ <(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_true_to_le β€¦ H) -H #H
-      cases (le_to_not_lt β€¦ H) -H #H cases (H ?) %
-    | whd in βŠ’ (??%?); >lt_to_leb_false // @le_S_S /2/ ]
-  | cases (true_or_false (eqb n k)) #H1 >H1 normalize
-    [ >(eqb_true_to_eq β€¦ H1) in H; #H lapply (leb_false_to_not_le β€¦ H) -H
-      * #H cases (H ?) %
-    | >le_to_leb_true // @not_lt_to_le % #H2 >le_to_leb_true in H;
-      [ #H destruct (H) | /2/ ]
-    ]
-  ]
-| #x0 #k whd in βŠ’ (??(?%??)?); cases (true_or_false (x0==x)) 
-  #H1 >H1 normalize // >(\P H1) >eqb_n_n % ]
-qed.      
-
-lemma vclose_vopen : βˆ€x,u.((Ξ½x.u)⌈xβŒ‰) = u. #x #u @vclose_vopen_aux
-qed.
-
-(*
-theorem tm_to_tm : βˆ€t.tm' t β†’ tm t.
-#t #H elim H
-*)
-
-lemma in_list_singleton : βˆ€T.βˆ€t1,t2:T.t1 βˆˆ [t2] β†’ t1 = t2.
-#T #t1 #t2 #H @(in_list_inv_ind ??? H) /2/
-qed.
-
-lemma fresh_vclose_tm_aux : βˆ€u,x,k.x βˆ‰ FV (vclose_tm_aux u x k).
-#u #x elim u //
-[ #n #k normalize cases (leb k n) normalize //
-| #x0 #k whd in βŠ’ (?(???(?%))); cases (true_or_false (x0==x)) #H >H normalize //
-  lapply (\Pf H) @not_to_not #Hin >(in_list_singleton ??? Hin) %
-| #v1 #v2 #IH1 #IH2 #k normalize % #Hin cases (in_list_append_to_or_in_list ???? Hin) -Hin #Hin
-  [ cases (IH1 k) -IH1 #IH1 @IH1 @Hin | cases (IH2 k) -IH2 #IH2 @IH2 @Hin ]
-qed.
-
-lemma fresh_vclose_tm : βˆ€u,x.x βˆ‰ FV (Ξ½x.u). //
-qed.
-
-lemma fresh_swap_tm : βˆ€z1,z2,u.z1 βˆ‰ FV u β†’ z2 βˆ‰ FV u β†’ swap π”Έ z1 z2 Β· u = u.
-#z1 #z2 #u elim u
-[2: normalize in βŠ’ (?β†’%β†’%β†’?); #x #Hz1 #Hz2 whd in βŠ’ (??%?); >swap_other //
-  [ @(not_to_not β€¦ Hz2) | @(not_to_not β€¦ Hz1) ] //
-|1: //
-| #s #v #IH normalize #Hz1 #Hz2 >IH // [@Hz2|@Hz1]
-| #v1 #v2 #IH1 #IH2 normalize #Hz1 #Hz2
-  >IH1 [| @(not_to_not β€¦ Hz2) @in_list_to_in_list_append_l | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_l ]
-  >IH2 // [@(not_to_not β€¦ Hz2) @in_list_to_in_list_append_r | @(not_to_not β€¦ Hz1) @in_list_to_in_list_append_r ]
-]
-qed.
-
-theorem tm_to_tm2 : βˆ€u.tm u β†’ tm2 u.
-#t #Ht elim Ht
-[ #n #Hn cases (not_le_Sn_O n) #Hfalse cases (Hfalse Hn)
-| @tm_par
-| #u #v #Hu #Hv @tm_app
-| #x #s #u #Hu #IHu <(vclose_vopen x u) @tm_lam
-  [ @fresh_vclose_tm
-  | #y #Hy <(fresh_swap_tm x y (Ξ½x.u)) /2/ @fresh_vclose_tm ]
-]
-qed.
-
-theorem tm2_to_tm : βˆ€u.tm2 u β†’ tm u.
-#u #pu elim pu /2/ #x #s #v #Hx #Hv #IH %4 @IH //
-qed.
-
-definition PAR β‰ Ξ»x.mk_TM (par x) ?. // qed.
-definition APP β‰ Ξ»u,v:TM.mk_TM (app u v) ?./2/ qed.
-definition LAM β‰ Ξ»x,s.Ξ»u:TM.mk_TM (lam x s u) ?./2/ qed.
-
-axiom vopen_tm_down : βˆ€u,x,k.tm_or_ctx (S k) u β†’ tm_or_ctx k (u⌈xβŒ‰).
-(* needs true_plus_false
-
-#u #x #k #Hu elim Hu
-[ #n #Hn normalize cases (true_or_false (eqb n O)) #H >H [%2]
-  normalize >(?: leb n O = false) [|cases n in H; // >eqb_n_n #H destruct (H) ]
-  normalize lapply Hn cases n in H; normalize [ #Hfalse destruct (Hfalse) ]
-  #n0 #_ #Hn0 % @le_S_S_to_le //
-| #x0 %2
-| #v1 #v2 #Hv1 #Hv2 #IH1 #IH2 %3 //
-| #x0 #s #v #Hv #IH normalize @daemon
-]
-qed.
-*)
-
-definition vopen_TM β‰ Ξ»u:CTX.Ξ»x.mk_TM (u⌈xβŒ‰) (vopen_tm_down β€¦). @ctx_of_CTX qed.
-
-axiom vclose_tm_up : βˆ€u,x,k.tm_or_ctx k u β†’ tm_or_ctx (S k) (Ξ½x.u).
-
-definition vclose_TM β‰ Ξ»u:TM.Ξ»x.mk_CTX (Ξ½x.u) (vclose_tm_up β€¦). @tm_of_TM qed.
-
-interpretation "ln wf term variable open" 'open u x = (vopen_TM u x).
-interpretation "ln wf term variable close" 'nu x u = (vclose_TM u x).
-
-theorem tm_alpha : βˆ€x,y,s,u.x βˆ‰ FV u β†’ y βˆ‰ FV u β†’ lam x s (u⌈xβŒ‰) = lam y s (u⌈yβŒ‰).
-#x #y #s #u #Hx #Hy whd in βŠ’ (??%%); @eq_f >nominal_eta // >nominal_eta //
-qed.
-
-theorem TM_ind_plus : 
-(* non si puΓ² dare il principio in modo dipendente (almeno utilizzando tm2)
-   la "prova" purtroppo Γ¨ in Type e non si puΓ² garantire che sia esattamente
-   quella che ci aspetteremmo
- *)
- βˆ€P:pretm β†’ Type[0].
-   (βˆ€x:𝔸.P (PAR x)) β†’ 
-   (βˆ€v1,v2:TM.P v1 β†’ P v2 β†’ P (APP v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s.βˆ€v:CTX.x βˆ‰ FV v β†’ x βˆ‰ C β†’ 
-     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (LAM x s (v⌈xβŒ‰))) β†’
- βˆ€u:TM.P u.
-#P #Hpar #Happ #C #Hlam * #u #pu elim (tm_to_tm2 u pu) //
-[ #v1 #v2 #pv1 #pv2 #IH1 #IH2 @(Happ (mk_TM β€¦) (mk_TM β€¦)) /2/
-| #x #s #v #Hx #pv #IH
-  lapply (p_fresh β€¦ (C@FV v)) letin x0 β‰ (N_fresh β€¦ (C@FV v)) #Hx0
-  >(?:lam x s (v⌈xβŒ‰) = lam x0 s (v⌈x0βŒ‰))
-  [|@tm_alpha // @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r ]
-  @(Hlam x0 s (mk_CTX v ?) ??)
-  [ <(nominal_eta β€¦ Hx) @vclose_tm_up @tm2_to_tm @pv //
-  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_r
-  | @(not_to_not β€¦ Hx0) @in_list_to_in_list_append_l
-  | @IH ]
-]
-qed.
-
-notation 
-"hvbox('nominal' u 'return' out 'with' 
-       [ 'xpar' ident x β‡’ f1 
-       | 'xapp' ident v1 ident v2 ident recv1 ident recv2 β‡’ f2 
-       | 'xlam' β¨ident y # C❩ ident s ident w ident py1 ident py2 ident recw β‡’ f3 ])"
-with precedence 48 
-for @{ TM_ind_plus $out (Ξ»${ident x}:?.$f1)
-       (Ξ»${ident v1}:?.Ξ»${ident v2}:?.Ξ»${ident recv1}:?.Ξ»${ident recv2}:?.$f2)
-       $C (Ξ»${ident y}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.Ξ»${ident recw}:?.$f3)
-       $u }.
-       
-(* include "basics/jmeq.ma".*)
-
-definition subst β‰ (Ξ»u:TM.Ξ»x,v.
-  nominal u return (Ξ»_.TM) with 
-  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ u ]
-  | xapp v1 v2 recv1 recv2 β‡’ APP recv1 recv2
-  | xlam β¨y # x::FV v❩ s w py1 py2 recw β‡’ LAM y s (recw y py1) ]).
-
-lemma fasfd : βˆ€s,v. pretm_of_TM (subst (LAM O s (PAR 1)) O v) = pretm_of_TM (LAM O s (PAR 1)).
-#s #v normalize in βŠ’ (??%?);
-
-
-theorem tm2_ind_plus : 
-(* non si puΓ² dare il principio in modo dipendente (almeno utilizzando tm2) *)
- βˆ€P:pretm β†’ Type[0].
-   (βˆ€x:𝔸.P (par x)) β†’ 
-   (βˆ€v1,v2.tm2 v1 β†’ tm2 v2 β†’ P v1 β†’ P v2 β†’ P (app v1 v2)) β†’ 
-   βˆ€C:list π”Έ.
-   (βˆ€x,s,v.x βˆ‰ FV v β†’ x βˆ‰ C β†’ (βˆ€y.y βˆ‰ FV v β†’ tm2 (v⌈yβŒ‰)) β†’ 
-     (βˆ€y.y βˆ‰ FV v β†’ P (v⌈yβŒ‰)) β†’ P (lam x s (v⌈xβŒ‰))) β†’
- βˆ€u.tm2 u β†’ P u.
-#P #Hpar #Happ #C #Hlam #u #pu elim pu /2/
-#x #s #v #px #pv #IH 
-lapply (p_fresh β€¦ (C@FV v)) letin y β‰ (N_fresh β€¦ (C@FV v)) #Hy
->(?:lam x s (v⌈xβŒ‰) = lam y s (v⌈yβŒ‰)) [| @tm_alpha // @(not_to_not β€¦ Hy) @in_list_to_in_list_append_r ]
-@Hlam /2/ lapply Hy -Hy @not_to_not #Hy
-[ @in_list_to_in_list_append_r @Hy | @in_list_to_in_list_append_l @Hy ]
-qed.
-
-definition check_tm β‰ 
-  Ξ»u.pretm_ind_plus ? (Ξ»_.true) (Ξ»_.false) 
-    (Ξ»v1,v2,r1,r2.r1 βˆ§ r2) [ ] (Ξ»x,s,v,pv1,pv2,rv.rv) u.
-
-(*
-lemma check_tm_complete : βˆ€u.tm u β†’ check_tm u = true.
-#u #pu @(tm2_ind_plus β€¦ [ ] β€¦ (tm_to_tm2 ? pu)) //
-[ #v1 #v2 #pv1 #pv2 #IH1 #IH2
-| #x #s #v #Hx1 #Hx2 #Hv #IH
-*)
-
-notation 
-"hvbox('nominal' u 'return' out 'with' 
-       [ 'xpar' ident x β‡’ f1 
-       | 'xapp' ident v1 ident v2 ident pv1 ident pv2 ident recv1 ident recv2 β‡’ f2 
-       | 'xlam' β¨ident y # C❩ ident s ident w ident py1 ident py2 ident pw ident recw β‡’ f3 ])"
-with precedence 48 
-for @{ tm2_ind_plus $out (Ξ»${ident x}:?.$f1)
-       (Ξ»${ident v1}:?.Ξ»${ident v2}:?.Ξ»${ident pv1}:?.Ξ»${ident pv2}:?.Ξ»${ident recv1}:?.Ξ»${ident recv2}:?.$f2)
-       $C (Ξ»${ident y}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.Ξ»${ident pw}:?.Ξ»${ident recw}:?.$f3)
-       ? (tm_to_tm2 ? $u) }.
-(* notation 
-"hvbox('nominal' u 'with' 
-       [ 'xlam' ident x # C ident s ident w β‡’ f3 ])"
-with precedence 48 
-for @{ tm2_ind_plus ???
- $C (Ξ»${ident x}:?.Ξ»${ident s}:?.Ξ»${ident w}:?.Ξ»${ident py1}:?.Ξ»${ident py2}:?.
-     Ξ»${ident pw}:?.Ξ»${ident recw}:?.$f3) $u (tm_to_tm2 ??) }.
-*)
-
-
-definition subst β‰ (Ξ»u.Ξ»pu:tm u.Ξ»x,v.
-  nominal pu return (Ξ»_.pretm) with 
-  [ xpar x0 β‡’ match x == x0 with [ true β‡’ v | false β‡’ u ]
-  | xapp v1 v2 pv1 pv2 recv1 recv2 β‡’ app recv1 recv2
-  | xlam β¨y # x::FV v❩ s w py1 py2 pw recw β‡’ lam y s (recw y py1) ]).
-  
-lemma fasfd : βˆ€x,s,u,p1,v. subst (lam x s u) p1 x v = lam x s u.
-#x #s #u #p1 #v
-
-
-definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,y.
-  tm2_ind_plus ?
-  (* par x0 *)              (Ξ»x0.match x == x0 with [ true β‡’ v | false β‡’ u ])
-  (* app v1 v2 *)           (Ξ»v1,v2,pv1,pv2,recv1,recv2.app recv1 recv2)
-  (* lam y#(x::FV v) s w *) (x::FV v) (Ξ»y,s,w,py1,py2,pw,recw.lam y s (recw y py1)) 
-  u (tm_to_tm2 β€¦ pu).
-check subst
-definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,v.
-  nominal u with 
-  [ xlam y # (x::FV v) s w ^ ? ].
-
-(*
-notation > "Ξ› ident x. ident T [ident x] β†¦ P"
-  with precedence 48 for @{'foo (Ξ»${ident x}.Ξ»${ident T}.$P)}.
-
-notation < "Ξ› ident x. ident T [ident x] β†¦ P"
-  with precedence 48 for @{'foo (Ξ»${ident x}:$Q.Ξ»${ident T}:$R.$P)}.
-*)
-
-(*
-notation 
-"hvbox('nominal' u 'with' 
-       [ 'xpar' ident x β‡’ f1 
-       | 'xapp' ident v1 ident v2  β‡’ f2
-       | 'xlam' ident x # C s w β‡’ f3 ])"
-with precedence 48 
-for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
- (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
- $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
-*)
-
-(*
-notation 
-"hvbox('nominal' u 'with' 
-       [ 'xpar' ident x ^ f1 
-       | 'xapp' ident v1 ident v2 ^ f2 ])"
-(*       | 'xlam' ident x # C s w ^ f3 ]) *)
-with precedence 48 
-for @{ tm2_ind_plus ? (Ξ»${ident x}:$Tx.$f1) 
- (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
- $C (Ξ»${ident x}:$Tx.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
-*)
-notation 
-"hvbox('nominal' u 'with' 
-       [ 'xpar' ident x ^ f1 
-       | 'xapp' ident v1 ident v2 ^ f2 ])"
-with precedence 48 
-for @{ tm2_ind_plus ? (Ξ»${ident x}:?.$f1) 
- (Ξ»${ident v1}:$Tv1.Ξ»${ident v2}:$Tv2.Ξ»${ident pv1}:$Tpv1.Ξ»${ident pv2}:$Tpv2.Ξ»${ident recv1}:$Trv1.Ξ»${ident recv2}:$Trv2.$f2)
- $C (Ξ»${ident x}:?.Ξ»${ident s}:$Ts.Ξ»${ident w}:$Tw.Ξ»${ident py1}:$Tpy1.Ξ»${ident py2}:$Tpy2.Ξ»${ident pw}:$Tpw.Ξ»${ident recw}:$Trw.$f3) $u (tm_to_tm2 ??) }.
-
-
-definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,v.
-  nominal u with 
-  [ xpar x0 ^ match x == x0 with [ true β‡’ v | false β‡’ u ]
-  | xapp v1 v2 ^ ? ].
-  | xlam y # (x::FV v) s w ^ ? ].
-  
-  
-  (* par x0 *)              (Ξ»x0.match x == x0 with [ true β‡’ v | false β‡’ u ])
-  (* app v1 v2 *)           (Ξ»v1,v2,pv1,pv2,recv1,recv2.app recv1 recv2)
-  (* lam y#(x::FV v) s w *) (x::FV v) (Ξ»y,s,w,py1,py2,pw,recw.lam y s (recw y py1)) 
-  u (tm_to_tm2 β€¦ pu).
-*)
-definition subst β‰ Ξ»u.Ξ»pu:tm u.Ξ»x,v.
-  tm2_ind_plus ?
-  (* par x0 *)              (Ξ»x0.match x == x0 with [ true β‡’ v | false β‡’ u ])
-  (* app v1 v2 *)           (Ξ»v1,v2,pv1,pv2,recv1,recv2.app recv1 recv2)
-  (* lam y#(x::FV v) s w *) (x::FV v) (Ξ»y,s,w,py1,py2,pw,recw.lam y s (recw y py1)) 
-  u (tm_to_tm2 β€¦ pu).
-
-check subst
-
-axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
-notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
-interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
-
-
-
-inductive judg : list tp β†’ tm β†’ tp β†’ Prop β‰ 
-| t_var : βˆ€g,n,t.Nth ? n g = Some ? t β†’ judg g (var n) t
-| t_app : βˆ€g,m,n,t,u.judg g m (arr t u) β†’ judg g n t β†’ judg g (app m n) u
-| t_abs : βˆ€g,t,m,u.judg (t::g) m u β†’ judg g (abs t m) (arr t u).
-
-definition Env := list (𝔸 Γ— tp).
-
-axiom vclose_env : Env β†’ list tp.
-axiom vclose_tm : Env β†’ tm β†’ tm.
-axiom Lam : π”Έ β†’ tp β†’ tm β†’ tm.
-definition Judg β‰ Ξ»G,M,T.judg (vclose_env G) (vclose_tm G M) T.
-definition dom β‰ Ξ»G:Env.map ?? (fst ??) G.
-
-definition sctx β‰ π”Έ Γ— tm.
-axiom swap_tm : π”Έ β†’ π”Έ β†’ tm β†’ tm.
-definition sctx_app : sctx β†’ π”Έ β†’ tm β‰ Ξ»M0,Y.let βŒ©X,MβŒͺ β‰ M0 in swap_tm X Y M.
-
-axiom in_list : βˆ€A:Type[0].A β†’ list A β†’ Prop.
-interpretation "list membership" 'mem x l = (in_list ? x l).
-interpretation "list non-membership" 'notmem x l = (Not (in_list ? x l)).
-
-axiom in_Env : π”Έ Γ— tp β†’ Env β†’ Prop.
-notation "X β—ƒ G" non associative with precedence 45 for @{'lefttriangle $X $G}.
-interpretation "Env membership" 'lefttriangle x l = (in_Env x l).
-
-let rec FV M β‰ match M with 
-  [ par X β‡’ [X]
-  | app M1 M2 β‡’ FV M1@FV M2
-  | abs T M0 β‡’ FV M0
-  | _ β‡’ [ ] ].
-
-(* axiom Lookup : π”Έ β†’ Env β†’ option tp. *)
-
-(* forma alto livello del judgment
-   t_abs* : βˆ€G,T,X,M,U.
-            (βˆ€Y βˆ‰ supp(M).Judg (〈Y,TβŒͺ::G) (M[Y]) U) β†’ 
-            Judg G (Lam X T (M[X])) (arr T U) *)
-
-(* prima dimostrare, poi perfezionare gli assiomi, poi dimostrarli *)
-
-axiom Judg_ind : βˆ€P:Env β†’ tm β†’ tp β†’ Prop.
-  (βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ P G (par X) T) β†’ 
-  (βˆ€G,M,N,T,U.
-    Judg G M (arr T U) β†’ Judg G N T β†’ 
-    P G M (arr T U) β†’ P G N T β†’ P G (app M N) U) β†’ 
-  (βˆ€G,T1,T2,X,M1.
-    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ Judg (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’
-    (βˆ€Y.Y βˆ‰ (FV (Lam X T1 (sctx_app M1 X))) β†’ P (〈Y,T1βŒͺ::G) (sctx_app M1 Y) T2) β†’ 
-    P G (Lam X T1 (sctx_app M1 X)) (arr T1 T2)) β†’ 
-  βˆ€G,M,T.Judg G M T β†’ P G M T.
-
-axiom t_par : βˆ€X,G,T.〈X,TβŒͺ β—ƒ G β†’ Judg G (par X) T.
-axiom t_app2 : βˆ€G,M,N,T,U.Judg G M (arr T U) β†’ Judg G N T β†’ Judg G (app M N) U.
-axiom t_Lam : βˆ€G,X,M,T,U.Judg (〈X,TβŒͺ::G) M U β†’ Judg G (Lam X T M) (arr T U).
-
-definition subenv β‰ Ξ»G1,G2.βˆ€x.x β—ƒ G1 β†’ x β—ƒ G2.
-interpretation "subenv" 'subseteq G1 G2 = (subenv G1 G2).
-
-axiom daemon : βˆ€P:Prop.P.
-
-theorem weakening : βˆ€G1,G2,M,T.G1 βŠ† G2 β†’ Judg G1 M T β†’ Judg G2 M T.
-#G1 #G2 #M #T #Hsub #HJ lapply Hsub lapply G2 -G2 change with (βˆ€G2.?)
-@(Judg_ind β€¦ HJ)
-[ #X #G #T0 #Hin #G2 #Hsub @t_par @Hsub //
-| #G #M0 #N #T0 #U #HM0 #HN #IH1 #IH2 #G2 #Hsub @t_app2
-  [| @IH1 // | @IH2 // ]
-| #G #T1 #T2 #X #M1 #HM1 #IH #G2 #Hsub @t_Lam @IH 
-  [ (* trivial property of Lam *) @daemon 
-  | (* trivial property of subenv *) @daemon ]
-]
-qed.
-
-(* Serve un tipo Tm per i termini localmente chiusi e i suoi principi di induzione e
-   ricorsione *)
\ No newline at end of file
diff --git a/matita/matita/lib/binding/names.ma b/matita/matita/lib/binding/names.ma
deleted file mode 100644 (file)
index bc5f07d..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-(**************************************************************************)
-(*       ___                                                              *)
-(*      ||M||                                                             *)
-(*      ||A||       A project by Andrea Asperti                           *)
-(*      ||T||                                                             *)
-(*      ||I||       Developers:                                           *)
-(*      ||T||         The HELM team.                                      *)
-(*      ||A||         http://helm.cs.unibo.it                             *)
-(*      \   /                                                             *)
-(*       \ /        This file is distributed under the terms of the       *)
-(*        v         GNU General Public License Version 2                  *)
-(*                                                                        *)
-(**************************************************************************)
-
-include "basics/logic.ma".
-include "basics/lists/in.ma".
-include "basics/types.ma".
-
-(*interpretation "list membership" 'mem x l = (in_list ? x l).*)
-
-record Nset : Type[1] β‰
-{
-  (* carrier is specified as a coercion: when an object X of type Nset is
-     given, but something of type Type is expected, Matita will insert a
-     hidden coercion: the user sees "X", but really means "carrier X"     *)
-  carrier :> DeqSet;
-  N_fresh : list carrier β†’ carrier;
-  p_fresh : βˆ€l.N_fresh l βˆ‰ l
-}.
-
-definition maxlist β‰
- Ξ»l.foldr ?? (Ξ»x,acc.max x acc) 0 l.
-
-definition natfresh β‰ Ξ»l.S (maxlist l).
-
-lemma le_max_1 : βˆ€x,y.x β‰€ max x y. /2/
-qed.
-
-lemma le_max_2 : βˆ€x,y.y β‰€ max x y. /2/
-qed.
-
-lemma le_maxlist : βˆ€l,x.x βˆˆ l β†’ x β‰€ maxlist l.
-#l elim l
-[#x #Hx @False_ind cases (not_in_list_nil ? x) #H1 /2/
-|#y #tl #IH #x #H1 change with (max ??) in βŠ’ (??%);
- cases (in_list_cons_case ???? H1);#H2;
- [ >H2 @le_max_1
- | whd in βŠ’ (??%); lapply (refl ? (leb y (maxlist tl)));
-   cases (leb y (maxlist tl)) in βŠ’ (???% β†’ %);#H3
-   [ @IH //
-   | lapply (IH ? H2) #H4
-     lapply (leb_false_to_not_le β€¦ H3) #H5
-     lapply (not_le_to_lt β€¦ H5) #H6
-     @(transitive_le β€¦ H4)
-     @(transitive_le β€¦ H6) %2 %
-   ]
- ]
-]
-qed.
-
-(* prove freshness for nat *)
-lemma lt_l_natfresh_l : βˆ€l,x.x βˆˆ l β†’ x < natfresh l.
-#l #x #H1 @le_S_S /2/
-qed.
-
-(*naxiom p_Xfresh : βˆ€l.βˆ€x:Xcarr.x βˆˆ l β†’ x β‰  ntm (Xfresh l) βˆ§ x β‰  ntp (Xfresh l).*)
-lemma p_natfresh : βˆ€l.natfresh l βˆ‰ l.
-#l % #H1 lapply (lt_l_natfresh_l β€¦ H1) #H2
-cases (lt_to_not_eq β€¦ H2) #H3 @H3 %
-qed.
-
-include "basics/finset.ma".
-
-definition X : Nset β‰ mk_Nset DeqNat β€¦.
-[ @natfresh
-| @p_natfresh
-]
-qed.
\ No newline at end of file
diff --git a/matita/matita/lib/finite_lambda/confluence.ma b/matita/matita/lib/finite_lambda/confluence.ma
deleted file mode 100644 (file)
index 32b7e3f..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-(*
-    ||M||  This file is part of HELM, an Hypertextual, Electronic        
-    ||A||  Library of Mathematics, developed at the Computer Science     
-    ||T||  Department of the University of Bologna, Italy.                     
-    ||I||                                                                 
-    ||T||  
-    ||A||  This file is distributed under the terms of the 
-    \   /  GNU General Public License Version 2        
-     \ /      
-      V_______________________________________________________________ *)
-
-include "finite_lambda/reduction.ma".
-
-   
-axiom canonical_to_T: βˆ€O,D.βˆ€M:T O D.βˆ€ty.(* type_of M ty β†’ *)
-  βˆƒa:FinSet_of_FType O D ty. star ? (red O D) M (to_T O D ty a).
-   
-axiom normal_to_T: βˆ€O,D,M,ty,a. red O D (to_T O D ty a) M β†’ False.
-
-axiom red_closed: βˆ€O,D,M,M1. 
-  is_closed O D 0 M β†’ red O D M M1 β†’ is_closed O D 0 M1.
-
-lemma critical: βˆ€O,D,ty,M,N. 
-  βˆƒM3:T O D
-  .star (T O D) (red O D) (subst O D M 0 N) M3
-   βˆ§star (T O D) (red O D)
-    (App O D
-     (Vec O D ty
-      (map (FinSet_of_FType O D ty) (T O D)
-       (Ξ»a0:FinSet_of_FType O D ty.subst O D M 0 (to_T O D ty a0))
-       (enum (FinSet_of_FType O D ty)))) N) M3.
-#O #D #ty #M #N
-lapply (canonical_to_T O D N ty) * #a #Ha
-%{(subst O D M 0 (to_T O D ty a))} (* CR-term *)
-%[@red_star_subst @Ha
- |@trans_star [|@(star_red_appr β€¦ Ha)] @R_to_star @riota
-  lapply (enum_complete (FinSet_of_FType O D ty) a)
-  elim (enum (FinSet_of_FType O D ty))
-   [normalize #H1 destruct (H1)
-   |#hd #tl #Hind #H cases (orb_true_l β€¦ H) -H #Hcase
-     [normalize >Hcase >(\P Hcase) //
-     |normalize cases (true_or_false (a==hd)) #Hcase1
-       [normalize >Hcase1 >(\P Hcase1) // |>Hcase1 @Hind @Hcase]
-     ]
-   ]
- ]
-qed.
-
-lemma critical2: βˆ€O,D,ty,a,M,M1,M2,v.
-  red O D (Vec O D ty v) M β†’
-  red O D (App O D (Vec O D ty v) (to_T O D ty a)) M1 β†’
-  assoc (FinSet_of_FType O D ty) (T O D) a (enum (FinSet_of_FType O D ty)) v
-    =Some (T O D) M2 β†’
-  βˆƒM3:T O D
-  .star (T O D) (red O D) M2 M3
-   βˆ§star (T O D) (red O D) (App O D M (to_T O D ty a)) M3.
-#O #D #ty #a #M #M1 #M2 #v #redM #redM1 #Ha lapply (red_vec β€¦ redM) -redM
-* #N * #N1 * #v1 * #v2 * * #Hred1 #Hv #HM0 >HM0 -HM0 >Hv in Ha; #Ha
-cases (same_assoc β€¦ a (enum (FinSet_of_FType O D ty)) v1 v2 N N1)
-  [* >Ha -Ha #H1 destruct (H1) #Ha
-   %{N1} (* CR-term *) % [@R_to_star //|@R_to_star @(riota β€¦ Ha)]
-  |#Ha1 %{M2} (* CR-term *) % [// | @R_to_star @riota <Ha1 @Ha]
-  ]
-qed.
-
-
-lemma critical3: βˆ€O,D,ty,M1,M2. red O D M1 M2 β†’ 
-  βˆƒM3:T O D.star (T O D) (red O D) (Lambda O D ty M2) M3
-   βˆ§star (T O D) (red O D)
-    (Vec O D ty
-     (map (FinSet_of_FType O D ty) (T O D)
-      (Ξ»a:FinSet_of_FType O D ty.subst O D M1 0 (to_T O D ty a))
-      (enum (FinSet_of_FType O D ty)))) M3.
-#O #D #ty #M1 #M2 #Hred
- %{(Vec O D ty
-    (map (FinSet_of_FType O D ty) (T O D)
-    (Ξ»a:FinSet_of_FType O D ty.subst O D M2 0 (to_T O D ty a))
-    (enum (FinSet_of_FType O D ty))))} (* CR-term *) %
-  [@R_to_star @rmem
-  |@star_red_vec2 [>length_map >length_map //] #n #M0
-   cases (true_or_false (leb (|enum (FinSet_of_FType O D ty)|) n)) #Hcase
-    [>nth_to_default [2:>length_map @(leb_true_to_le β€¦ Hcase)]
-     >nth_to_default [2:>length_map @(leb_true_to_le β€¦ Hcase)] //
-    |cut (n < |enum (FinSet_of_FType O D ty)|) 
-      [@not_le_to_lt @leb_false_to_not_le @Hcase] #Hlt
-     cut (βˆƒa:FinSet_of_FType O D ty.True)
-      [lapply Hlt lapply (enum_complete (FinSet_of_FType O D ty))
-       cases (enum (FinSet_of_FType O D ty)) 
-        [#_ normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
-        |#a #l #_ #_ %{a} //
-        ]
-      ] * #a #_
-     >(nth_map ?????? a Hlt) >(nth_map ?????? a Hlt) #_
-     @red_star_subst2 // 
-    ]
-  ]
-qed.
-
-(* we need to proceed by structural induction on the term and then
-by inversion on the two redexes. The problem are the moves in a 
-same subterm, since we need an induction hypothesis, there *)
-
-lemma local_confluence: βˆ€O,D,M,M1,M2. red O D M M1 β†’ red O D M M2 β†’ 
-βˆƒM3. star ? (red O D) M1 M3 βˆ§ star ? (red O D) M2 M3. 
-#O #D #M @(T_elim β€¦ M)
-  [#o #a #M1 #M2 #H elim(red_val ????? H)
-  |#n #M1 #M2 #H elim(red_rel ???? H)
-  |(* app : this is the interesting case *)
-   #P #Q #HindP #HindQ
-   #M1 #M2 #H1 inversion H1 -H1
-    [(* right redex is beta *)
-     #ty #Q #N #Hc #HM >HM -HM #HM1 >HM1 - HM1 #Hl inversion Hl
-      [#ty1 #Q1 #N1 #Hc1 #H1 destruct (H1) #H_ 
-       %{(subst O D Q1 0 N1)} (* CR-term *) /2/
-      |#ty #v #a #M0 #_ #H1 destruct (H1) (* vacuous *)
-      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #_ cases (red_lambda β€¦ redM0)
-        [* #Q1 * #redQ #HM10 >HM10 
-         %{(subst O D Q1 0 N0)} (* CR-term *) %
-          [@red_star_subst2 //|@R_to_star @rbeta @Hc]
-        |#HM1 >HM1 @critical
-        ]
-      |#M0 #N0 #N1 #redN0N1 #_ #H1 destruct (H1) #HM2
-       %{(subst O D Q 0 N1)} (* CR-term *) 
-       %[@red_star_subst @R_to_star //|@R_to_star @rbeta @(red_closed β€¦ Hc) //]
-      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
-      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      ] 
-    |(* right redex is iota *)#ty #v #a #M3 #Ha #_ #_ #Hl inversion Hl
-      [#P1 #M1 #N1 #_ #H1 destruct (H1) (* vacuous *)
-      |#ty1 #v1 #a1 #M4 #Ha1 #H1 destruct (H1) -H1 #HM4 >(inj_to_T β€¦ e0) in Ha;
-       >Ha1 #H1 destruct (H1) %{M3} (* CR-term *) /2/
-      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #HM2 @(critical2 β€¦ redM0 Hl Ha)
-      |#M0 #N0 #N1 #redN0N1 #_ #H1 destruct (H1) elim (normal_to_T β€¦ redN0N1)
-      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
-      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      ]
-    |(* right redex is appl *)#M3 #M4 #N #redM3M4 #_ #H1 destruct (H1) #_ 
-      #Hl inversion Hl
-      [#ty1 #M1 #N1 #Hc #H1 destruct (H1) #HM2 lapply (red_lambda β€¦ redM3M4) *
-        [* #M3 * #H1 #H2 >H2 %{(subst O D M3 0 N1)} %
-          [@R_to_star @rbeta @Hc|@red_star_subst2 // ]
-        |#H >H -H lapply (critical O D ty1 M1 N1) * #M3 * #H1 #H2 
-         %{M3} /2/
-        ]
-      |#ty1 #v1 #a1 #M4 #Ha1 #H1 #H2 destruct 
-       lapply (critical2 β€¦ redM3M4 Hl Ha1) * #M3 * #H1 #H2 %{M3} /2/
-      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #HM2 
-       lapply (HindP β€¦ redM0 redM3M4) * #M3 * #H1 #H2 
-       %{(App O D M3 N0)} (* CR-term *) % [@star_red_appl //|@star_red_appl //]
-      |#M0 #N0 #N1 #redN0N1 #_ #H1 destruct (H1) #_
-       %{(App O D M4 N1)} % @R_to_star [@rappr //|@rappl //]
-      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
-      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      ]
-    |(* right redex is appr *)#M3 #N #N1 #redN #_ #H1 destruct (H1) #_ 
-      #Hl inversion Hl
-      [#ty1 #M0 #N0 #Hc #H1 destruct (H1) #HM2 
-       %{(subst O D M0 0 N1)} (* CR-term *) % 
-        [@R_to_star @rbeta @(red_closed β€¦ Hc) //|@red_star_subst @R_to_star // ]
-      |#ty1 #v1 #a1 #M4 #Ha1 #H1 #H2 destruct (H1) elim (normal_to_T β€¦ redN)
-      |#M0 #M10 #N0 #redM0 #_ #H1 destruct (H1) #HM2 
-       %{(App O D M10 N1)} (* CR-term *) % @R_to_star [@rappl //|@rappr //]
-      |#M0 #N0 #N10 #redN0 #_ #H1 destruct (H1) #_
-       lapply (HindQ β€¦ redN0 redN) * #M3 * #H1 #H2 
-       %{(App O D M0 M3)} (* CR-term *) % [@star_red_appr //|@star_red_appr //]
-      |#ty1 #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      |#ty1 #M0 #H1 destruct (H1) (* vacuous *)
-      |#ty1 #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1) (* vacuous *)
-      ]
-    |(* right redex is rlam *) #ty #N0 #N1 #_ #_ #H1 destruct (H1) (* vacuous *)
-    |(* right redex is rmem *) #ty #M0 #H1 destruct (H1) (* vacuous *)
-    |(* right redex is vec *) #ty #N #N1 #v #v1 #_ #_ 
-     #H1 destruct (H1) (* vacuous *)
-    ]
-  |#ty #M1 #Hind #M2 #M3 #H1 #H2 (* this case is not trivial any more *)
-   lapply (red_lambda β€¦ H1) *
-    [* #M4 * #H3 #H4 >H4 lapply (red_lambda β€¦ H2) *
-      [* #M5 * #H5 #H6 >H6 lapply(Hind β€¦ H3 H5) * #M6 * #H7 #H8 
-       %{(Lambda O D ty M6)} (* CR-term *) % @star_red_lambda //
-      |#H5 >H5 @critical3 // 
-      ]
-    |#HM2 >HM2 lapply (red_lambda β€¦ H2) *
-      [* #M4 * #Hred #HM3 >HM3 lapply (critical3 β€¦ ty ?? Hred) * #M5
-       * #H3 #H4 %{M5} (* CR-term *) % //
-      |#HM3 >HM3 %{M3} (* CR-term *) % // 
-      ]
-    ]
-  |#ty #v1 #Hind #M1 #M2 #H1 #H2
-   lapply (red_vec β€¦ H1) * #N11 * #N12 * #v11 * #v12 * * #redN11 #Hv1 #HM1
-   lapply (red_vec β€¦ H2) * #N21* #N22 * #v21 * #v22 * * #redN21 #Hv2 #HM2
-   >Hv1 in Hv2; #Hvv lapply (compare_append β€¦ Hvv) -Hvv * 
-   (* we must proceed by cases on the list *) * normalize
-    [(* N11 = N21 *) *
-      [>append_nil * #Hl1 #Hl2 destruct lapply(Hind N11 β€¦ redN11 redN21)
-        [@mem_append_l2 %1 //]
-       * #M3 * #HM31 #HM32
-       %{(Vec O D ty (v21@M3::v12))} (* CR-term *) 
-       % [@star_red_vec //|@star_red_vec //]
-      |>append_nil * #Hl1 #Hl2 destruct lapply(Hind N21 β€¦ redN21 redN11)
-        [@mem_append_l2 %1 //]
-       * #M3 * #HM31 #HM32
-       %{(Vec O D ty (v11@M3::v22))} (* CR-term *) 
-       % [@star_red_vec //|@star_red_vec //]
-      ]
-    |(* N11 β‰   N21 *) -Hind #P #l *
-      [* #Hv11 #Hv22 destruct
-       %{((Vec O D ty ((v21@N22::l)@N12::v12)))} (* CR-term *) % @R_to_star 
-        [>associative_append >associative_append normalize @rvec //
-        |>append_cons <associative_append <append_cons in βŠ’ (???%?); @rvec //
-        ]
-      |* #Hv11 #Hv22 destruct
-       %{((Vec O D ty ((v11@N12::l)@N22::v22)))} (* CR-term *) % @R_to_star 
-        [>append_cons <associative_append <append_cons in βŠ’ (???%?); @rvec //
-        |>associative_append >associative_append normalize @rvec //
-        ]
-      ]
-    ]
-  ]
-qed.    
-      
-
-
-
diff --git a/matita/matita/lib/finite_lambda/reduction.ma b/matita/matita/lib/finite_lambda/reduction.ma
deleted file mode 100644 (file)
index 98c56e1..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-(*
-    ||M||  This file is part of HELM, an Hypertextual, Electronic        
-    ||A||  Library of Mathematics, developed at the Computer Science     
-    ||T||  Department of the University of Bologna, Italy.                     
-    ||I||                                                                 
-    ||T||  
-    ||A||  This file is distributed under the terms of the 
-    \   /  GNU General Public License Version 2        
-     \ /      
-      V_______________________________________________________________ *)
-
-include "finite_lambda/terms_and_types.ma".
-
-(* some auxiliary lemmas *)
-
-lemma nth_to_default: βˆ€A,l,n,d. 
-  |l| β‰€ n β†’ nth n A l d = d.
-#A #l elim l [//] #a #tl #Hind #n cases n
-  [#d normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
-  |#m #d normalize #H @Hind @le_S_S_to_le @H
-  ]
-qed.
-
-lemma mem_nth: βˆ€A,l,n,d. 
-  n < |l|  β†’ mem ? (nth n A l d) l.
-#A #l elim l   
-  [#n #d normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
-  |#a #tl #Hind * normalize 
-    [#_ #_ %1 //| #m #d #HSS %2 @Hind @le_S_S_to_le @HSS]
-  ]
-qed.
-
-lemma nth_map: βˆ€A,B,l,f,n,d1,d2. 
-  n < |l| β†’ nth n B (map β€¦ f l) d1 = f (nth n A l d2).
-#n #B #l #f elim l 
-  [#m #d1 #d2 normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
-  |#a #tl #Hind #m #d1 #d2 cases m normalize // 
-   #m1 #H @Hind @le_S_S_to_le @H
-  ]
-qed.
-
-
-
-(* end of auxiliary lemmas *)
-
-let rec to_T O D ty on ty: FinSet_of_FType O D ty β†’ T O D β‰ 
-  match ty return (Ξ»ty.FinSet_of_FType O D ty β†’ T O D) with 
-  [atom o β‡’ Ξ»a.Val O D o a
-  |arrow ty1 ty2 β‡’ Ξ»a:FinFun ??.Vec O D ty1  
-    (map ((FinSet_of_FType O D ty1)Γ—(FinSet_of_FType O D ty2)) 
-     (T O D) (Ξ»p.to_T O D ty2 (snd β€¦ p)) (pi1 β€¦ a))
-  ]
-.
-
-lemma is_closed_to_T: βˆ€O,D,ty,a. is_closed O D 0 (to_T O D ty a).
-#O #D #ty elim ty //
-#ty1 #ty2 #Hind1 #Hind2 #a normalize @cvec #m #Hmem
-lapply (mem_map ????? Hmem) * #a1 * #H1 #H2 <H2 @Hind2 
-qed.
-
-axiom inj_to_T: βˆ€O,D,ty,a1,a2. to_T O D ty a1 = to_T O D ty a2 β†’ a1 = a2. 
-(* complicata 
-#O #D #ty elim ty 
-  [#o normalize #a1 #a2 #H destruct //
-  |#ty1 #ty2 #Hind1 #Hind2 * #l1 #Hl1 * #l2 #Hl2 normalize #H destruct -H
-   cut (l1=l2) [2: #H generalize in match Hl1; >H //] -Hl1 -Hl2
-   lapply e0 -e0 lapply l2 -l2 elim l1 
-    [#l2 cases l2 normalize [// |#a1 #tl1 #H destruct]
-    |#a1 #tl1 #Hind #l2 cases l2 
-      [normalize #H destruct
-      |#a2 #tl2 normalize #H @eq_f2
-        [@Hind2 *)
-        
-let rec assoc (A:FinSet) (B:Type[0]) (a:A) l1 l2 on l1 : option B β‰
-  match l1 with
-  [ nil β‡’  None ?
-  | cons hd1 tl1 β‡’ match l2 with
-    [ nil β‡’ None ?
-    | cons hd2 tl2 β‡’ if a==hd1 then Some ? hd2 else assoc A B a tl1 tl2
-    ]
-  ]. 
-  
-lemma same_assoc: βˆ€A,B,a,l1,v1,v2,N,N1.
-  assoc A B a l1 (v1@N::v2) = Some ? N βˆ§ assoc A B a l1 (v1@N1::v2) = Some ? N1 
-   βˆ¨ assoc A B a l1 (v1@N::v2) = assoc A B a l1 (v1@N1::v2).
-#A #B #a #l1 #v1 #v2 #N #N1 lapply v1 -v1 elim l1 
-  [#v1 %2 // |#hd #tl #Hind * normalize cases (a==hd) normalize /3/]
-qed.
-
-lemma assoc_to_mem: βˆ€A,B,a,l1,l2,b. 
-  assoc A B a l1 l2 = Some ? b β†’ mem ? b l2.
-#A #B #a #l1 elim l1
-  [#l2 #b normalize #H destruct
-  |#hd1 #tl1 #Hind * 
-    [#b normalize #H destruct
-    |#hd2 #tl2 #b normalize cases (a==hd1) normalize
-      [#H %1 destruct //|#H %2 @Hind @H]
-    ]
-  ]
-qed.
-
-lemma assoc_to_mem2: βˆ€A,B,a,l1,l2,b. 
-  assoc A B a l1 l2 = Some ? b β†’ βˆƒl21,l22.l2=l21@b::l22.
-#A #B #a #l1 elim l1
-  [#l2 #b normalize #H destruct
-  |#hd1 #tl1 #Hind * 
-    [#b normalize #H destruct
-    |#hd2 #tl2 #b normalize cases (a==hd1) normalize
-      [#H %{[]} %{tl2} destruct //
-      |#H lapply (Hind β€¦ H) * #la * #lb #H1 
-       %{(hd2::la)} %{lb} >H1 //]
-    ]
-  ]
-qed.
-
-lemma assoc_map: βˆ€A,B,C,a,l1,l2,f,b. 
-  assoc A B a l1 l2 = Some ? b β†’ assoc A C a l1 (map ?? f l2) = Some ? (f b).
-#A #B #C #a #l1 elim l1
-  [#l2 #f #b normalize #H destruct
-  |#hd1 #tl1 #Hind * 
-    [#f #b normalize #H destruct
-    |#hd2 #tl2 #f #b normalize cases (a==hd1) normalize
-      [#H destruct // |#H @(Hind β€¦ H)]
-    ]
-  ]
-qed.
-
-(*************************** One step reduction *******************************)
-
-inductive red (O:Type[0]) (D:Oβ†’FinSet) : T O D  β†’T O D β†’ Prop β‰
-  | (* we only allow beta on closed arguments *)
-    rbeta: βˆ€P,M,N. is_closed O D 0 N β†’
-      red O D (App O D (Lambda O D P M) N) (subst O D M 0 N)
-  | riota: βˆ€ty,v,a,M. 
-      assoc ?? a (enum (FinSet_of_FType O D ty)) v = Some ? M β†’
-      red O D (App O D (Vec O D ty v) (to_T O D ty a)) M
-  | rappl: βˆ€M,M1,N. red O D M M1 β†’ red O D (App O D M N) (App O D M1 N)
-  | rappr: βˆ€M,N,N1. red O D N N1 β†’ red O D (App O D M N) (App O D M N1)
-  | rlam: βˆ€ty,N,N1. red O D N N1 β†’ red O D (Lambda O D ty N) (Lambda O D ty N1) 
-  | rmem: βˆ€ty,M. red O D (Lambda O D ty M)
-      (Vec O D ty (map ?? (Ξ»a. subst O D M 0 (to_T O D ty a)) 
-      (enum (FinSet_of_FType O D ty)))) 
-  | rvec: βˆ€ty,N,N1,v,v1. red O D N N1 β†’ 
-      red O D (Vec O D ty (v@N::v1)) (Vec O D ty (v@N1::v1)).
-(*********************************** inversion ********************************)
-lemma red_vec: βˆ€O,D,ty,v,M.
-  red O D (Vec O D ty v) M β†’ βˆƒN,N1,v1,v2.
-      red O D N N1 βˆ§ v = v1@N::v2 βˆ§ M = Vec O D ty (v1@N1::v2).
-#O #D #ty #v #M #Hred inversion Hred
-  [#ty1 #M0 #N #Hc #H destruct
-  |#ty1 #v1 #a #M0 #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#ty1 #M #M1 #_ #_ #H destruct
-  |#ty1 #M0 #H destruct
-  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct #_ %{N} %{N1} %{v1} %{v2} /3/
-  ]
-qed.
-      
-lemma red_lambda: βˆ€O,D,ty,M,N.
-  red O D (Lambda O D ty M) N β†’ 
-      (βˆƒM1. red O D M M1 βˆ§ N = (Lambda O D ty M1)) βˆ¨
-      N = Vec O D ty (map ?? (Ξ»a. subst O D M 0 (to_T O D ty a)) 
-      (enum (FinSet_of_FType O D ty))).
-#O #D #ty #M #N #Hred inversion Hred
-  [#ty1 #M0 #N #Hc #H destruct
-  |#ty1 #v1 #a #M0 #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#ty1 #P #P1 #redP #_ #H #H1 destruct %1 %{P1} % //
-  |#ty1 #M0 #H destruct #_ %2 //
-  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct
-  ]
-qed. 
-
-lemma red_val: βˆ€O,D,ty,a,N.
-  red O D (Val O D ty a) N β†’ False.
-#O #D #ty #M #N #Hred inversion Hred
-  [#ty1 #M0 #N #Hc #H destruct
-  |#ty1 #v1 #a #M0 #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#ty1 #N1 #N2 #_ #_ #H destruct
-  |#ty1 #M0 #H destruct #_ 
-  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct
-  ]
-qed. 
-
-lemma red_rel: βˆ€O,D,n,N.
-  red O D (Rel O D n) N β†’ False.
-#O #D #n #N #Hred inversion Hred
-  [#ty1 #M0 #N #Hc #H destruct
-  |#ty1 #v1 #a #M0 #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#M0 #M1 #N #_ #_ #H destruct
-  |#ty1 #N1 #N2 #_ #_ #H destruct
-  |#ty1 #M0 #H destruct #_ 
-  |#ty1 #N #N1 #v1 #v2 #Hred1 #_ #H destruct
-  ]
-qed. 
-(*************************** multi step reduction *****************************)
-lemma star_red_appl: βˆ€O,D,M,M1,N. star ? (red O D) M M1 β†’ 
-  star ? (red O D) (App O D M N) (App O D M1 N).
-#O #D #M #N #N1 #H elim H // 
-#P #Q #Hind #HPQ #Happ %1[|@Happ] @rappl @HPQ
-qed.
-
-lemma star_red_appr: βˆ€O,D,M,N,N1. star ? (red O D) N N1 β†’ 
-  star ? (red O D) (App O D M N) (App O D M N1).
-#O #D #M #N #N1 #H elim H // 
-#P #Q #Hind #HPQ #Happ %1[|@Happ] @rappr @HPQ
-qed.
-
-lemma star_red_vec: βˆ€O,D,ty,N,N1,v1,v2. star ? (red O D) N N1 β†’ 
-  star ? (red O D) (Vec O D ty (v1@N::v2)) (Vec O D ty (v1@N1::v2)).
-#O #D #ty #N #N1 #v1 #v2 #H elim H // 
-#P #Q #Hind #HPQ #Hvec %1[|@Hvec] @rvec @HPQ
-qed.
-
-lemma star_red_vec1: βˆ€O,D,ty,v1,v2,v. |v1| = |v2| β†’
-  (βˆ€n,M. n < |v1| β†’ star ? (red O D) (nth n ? v1 M) (nth n ? v2 M)) β†’ 
-  star ? (red O D) (Vec O D ty (v@v1)) (Vec O D ty (v@v2)).
-#O #D #ty #v1 elim v1 
-  [#v2 #v normalize #Hv2 >(lenght_to_nil β€¦ (sym_eq β€¦ Hv2)) normalize //
-  |#N1 #tl1 #Hind * [normalize #v #H destruct] #N2 #tl2 #v normalize #HS
-   #H @(trans_star β€¦ (Vec O D ty (v@N2::tl1)))
-    [@star_red_vec @(H 0 N1) @le_S_S //
-    |>append_cons >(append_cons ??? tl2) @(Hind… (injective_S β€¦ HS))
-     #n #M #H1 @(H (S n)) @le_S_S @H1
-    ]
-  ]
-qed.
-
-lemma star_red_vec2: βˆ€O,D,ty,v1,v2. |v1| = |v2| β†’
-  (βˆ€n,M. n < |v1| β†’ star ? (red O D) (nth n ? v1 M) (nth n ? v2 M)) β†’ 
-  star ? (red O D) (Vec O D ty v1) (Vec O D ty v2).
-#O #D #ty #v1 #v2 @(star_red_vec1 β€¦ [ ])
-qed.
-
-lemma star_red_lambda: βˆ€O,D,ty,N,N1. star ? (red O D) N N1 β†’ 
-  star ? (red O D) (Lambda O D ty N) (Lambda O D ty N1).
-#O #D #ty #N #N1 #H elim H // 
-#P #Q #Hind #HPQ #Hlam %1[|@Hlam] @rlam @HPQ
-qed.
-
-(************************ reduction and substitution **************************)
-  
-lemma red_star_subst : βˆ€O,D,M,N,N1,i. 
-  star ? (red O D) N N1 β†’ star ? (red O D) (subst O D M i N) (subst O D M i N1).
-#O #D #M #N #N1 #i #Hred lapply i -i @(T_elim β€¦ M) normalize
-  [#o #a #i //
-  |#i #n cases (leb n i) normalize // cases (eqb n i) normalize //
-  |#P #Q #HindP #HindQ #n normalize 
-   @(trans_star β€¦ (App O D (subst O D P n N1) (subst O D Q n N))) 
-    [@star_red_appl @HindP |@star_red_appr @HindQ]
-  |#ty #P #HindP #i @star_red_lambda @HindP
-  |#ty #v #Hindv #i @star_red_vec2 [>length_map >length_map //]
-   #j #Q inversion v [#_ normalize //] #a #tl #_ #Hv
-   cases (true_or_false (leb (S j) (|a::tl|))) #Hcase
-    [lapply (leb_true_to_le β€¦ Hcase) -Hcase #Hcase
-     >(nth_map ?????? a Hcase) >(nth_map ?????? a Hcase) #_ @Hindv >Hv @mem_nth //
-    |>nth_to_default 
-      [2:>length_map @le_S_S_to_le @not_le_to_lt @leb_false_to_not_le //]
-     >nth_to_default 
-      [2:>length_map @le_S_S_to_le @not_le_to_lt @leb_false_to_not_le //] //
-    ]
-  ]
-qed.
-     
-lemma red_star_subst2 : βˆ€O,D,M,M1,N,i. is_closed O D 0 N β†’ 
-  red O D M M1 β†’ star ? (red O D) (subst O D M i N) (subst O D M1 i N).
-#O #D #M #M1 #N #i #HNc #Hred lapply i -i elim Hred
-  [#ty #P #Q #HQc #i normalize @starl_to_star @sstepl 
-   [|@rbeta >(subst_closed β€¦ HQc) //] >(subst_closed β€¦ HQc) // 
-    lapply (subst_lemma ?? P ?? i 0 (is_closed_mono β€¦ HQc) HNc) // 
-    <plus_n_Sm <plus_n_O #H <H //
-  |#ty #v #a #P #HP #i normalize >(subst_closed β€¦ (le_O_n β€¦)) //
-   @R_to_star @riota @assoc_map @HP 
-  |#P #P1 #Q #Hred #Hind #i normalize @star_red_appl @Hind
-  |#P #P1 #Q #Hred #Hind #i normalize @star_red_appr @Hind
-  |#ty #P #P1 #Hred #Hind #i normalize @star_red_lambda @Hind
-  |#ty #P #i normalize @starl_to_star @sstepl [|@rmem] 
-   @star_to_starl @star_red_vec2 [>length_map >length_map >length_map //]
-   #n #Q >length_map #H
-   cut (βˆƒa:(FinSet_of_FType O D ty).True) 
-    [lapply H -H lapply (enum_complete (FinSet_of_FType O D ty))
-     cases (enum (FinSet_of_FType O D ty)) 
-      [#x normalize #H @False_ind @(absurd β€¦ H) @lt_to_not_le //
-      |#x #l #_ #_ %{x} //
-      ]
-    ] * #a #_
-   >(nth_map ?????? a H) >(nth_map ?????? Q) [2:>length_map @H] 
-   >(nth_map ?????? a H) 
-   lapply (subst_lemma O D P (to_T O D ty
-    (nth n (FinSet_of_FType O D ty) (enum (FinSet_of_FType O D ty)) a)) 
-   N i 0 (is_closed_mono β€¦ (is_closed_to_T β€¦)) HNc) // <plus_n_O #H1 >H1
-   <plus_n_Sm <plus_n_O //
-  |#ty #P #Q #v #v1 #Hred #Hind #n normalize 
-   <map_append <map_append @star_red_vec @Hind
-  ]
-qed.
-   
-
-
-
-
diff --git a/matita/matita/lib/finite_lambda/terms_and_types.ma b/matita/matita/lib/finite_lambda/terms_and_types.ma
deleted file mode 100644 (file)
index 1ae47c2..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-(*
-    ||M||  This file is part of HELM, an Hypertextual, Electronic        
-    ||A||  Library of Mathematics, developed at the Computer Science     
-    ||T||  Department of the University of Bologna, Italy.                     
-    ||I||                                                                 
-    ||T||  
-    ||A||  This file is distributed under the terms of the 
-    \   /  GNU General Public License Version 2        
-     \ /      
-      V_______________________________________________________________ *)
-
-include "basics/finset.ma".
-include "basics/star.ma".
-
-
-inductive FType (O:Type[0]): Type[0] β‰
-  | atom : O β†’ FType O 
-  | arrow : FType O β†’ FType O β†’ FType O. 
-
-inductive T (O:Type[0]) (D:O β†’ FinSet): Type[0] β‰
-  | Val: βˆ€o:O.carr (D o) β†’ T O D        (* a value in a finset *)
-  | Rel: nat β†’ T O D                    (* DB index, base is 0 *)
-  | App: T O D β†’ T O D β†’ T O D          (* function, argument *)
-  | Lambda: FType O β†’ T O D β†’ T O D     (* type, body *)
-  | Vec: FType O β†’ list (T O D) β†’ T O D (* type, body *)
-.
-
-let rec FinSet_of_FType O (D:Oβ†’FinSet) (ty:FType O) on ty : FinSet β‰
-  match ty with
-  [atom o β‡’ D o
-  |arrow ty1 ty2 β‡’ FinFun (FinSet_of_FType O D ty1) (FinSet_of_FType O D ty2)
-  ].
-
-(* size *)
-
-let rec size O D (M:T O D) on M β‰
-match M with
-  [Val o a β‡’ 1
-  |Rel n β‡’ 1
-  |App P Q β‡’ size O D P + size O D Q + 1
-  |Lambda Ty P β‡’ size O D P + 1
-  |Vec Ty v β‡’ foldr ?? (Ξ»x,a. size O D x + a) 0 v +1
-  ]
-.
-
-(* axiom pos_size: βˆ€M. 1 β‰€ size M. *)
-
-theorem Telim_size: βˆ€O,D.βˆ€P: T O D β†’ Prop. 
- (βˆ€M. (βˆ€N. size O D N < size O D M β†’ P N) β†’ P M) β†’ βˆ€M. P M.
-#O #D #P #H #M (cut (βˆ€p,N. size O D N = p β†’ P N))
-  [2: /2/]
-#p @(nat_elim1 p) #m #H1 #N #sizeN @H #N0 #Hlt @(H1 (size O D N0)) //
-qed.
-
-lemma T_elim: 
-  βˆ€O: Type[0].βˆ€D:Oβ†’FinSet.βˆ€P:T O Dβ†’Prop.
-  (βˆ€o:O.βˆ€x:D o.P (Val O D o x)) β†’
-  (βˆ€n:β„•.P(Rel O D n)) β†’
-  (βˆ€m,n:T O D.P mβ†’P nβ†’P (App O D m n)) β†’
-  (βˆ€Ty:FType O.βˆ€m:T O D.P mβ†’P(Lambda O D Ty m)) β†’
-  (βˆ€Ty:FType O.βˆ€v:list (T O D).
-     (βˆ€x:T O D. mem ? x v β†’ P x) β†’ P(Vec O D Ty v)) β†’
-  βˆ€x:T O D.P x.
-#O #D #P #Hval #Hrel #Happ #Hlam #Hvec @Telim_size #x cases x //
-  [ (* app *) #m #n #Hind @Happ @Hind // /2 by le_minus_to_plus/
-  | (* lam *) #ty #m #Hind @Hlam @Hind normalize // 
-  | (* vec *) #ty #v #Hind @Hvec #x lapply Hind elim v
-    [#Hind normalize *
-    |#hd #tl #Hind1 #Hind2 * 
-      [#Hx >Hx @Hind2 normalize //
-      |@Hind1 #N #H @Hind2 @(lt_to_le_to_lt β€¦ H) normalize //
-      ]
-    ]
-  ]
-qed.
-
-(* since we only consider beta reduction with closed arguments we could avoid
-lifting. We define it for the sake of generality *)
-        
-(* arguments: k is the nesting depth (starts from 0), p is the lift 
-let rec lift O D t k p on t β‰ 
-  match t with 
-    [ Val o a β‡’ Val O D o a
-    | Rel n β‡’ if (leb k n) then Rel O D (n+p) else Rel O D n
-    | App m n β‡’ App O D (lift O D m k p) (lift O D n k p)
-    | Lambda Ty n β‡’ Lambda O D Ty (lift O D n (S k) p)
-    | Vec Ty v β‡’ Vec O D Ty (map ?? (Ξ»x. lift O D x k p) v) 
-    ].
-
-notation "↑ ^ n ( M )" non associative with precedence 40 for @{'Lift 0 $n $M}.
-notation "↑ _ k ^ n ( M )" non associative with precedence 40 for @{'Lift $n $k $M}.
-
-interpretation "Lift" 'Lift n k M = (lift ?? M k n). 
-
-let rec subst O D t k s on t β‰ 
-  match t with 
-    [ Val o a β‡’ Val O D o a 
-    | Rel n β‡’ if (leb k n) then
-        (if (eqb k n) then lift O D s 0 n else Rel O D (n-1)) 
-        else(Rel O D n)
-    | App m n β‡’ App O D (subst O D m k s) (subst O D n k s)
-    | Lambda T n β‡’ Lambda O D T (subst O D n (S k) s)
-    | Vec T v β‡’ Vec O D T (map ?? (Ξ»x. subst O D x k s) v) 
-    ].
-*)
-
-(* simplified version of subst, assuming the argument s is closed *)
-
-let rec subst O D t k s on t β‰ 
-  match t with 
-    [ Val o a β‡’ Val O D o a 
-    | Rel n β‡’ if (leb k n) then
-        (if (eqb k n) then (* lift O D s 0 n*) s else Rel O D (n-1)) 
-        else(Rel O D n)
-    | App m n β‡’ App O D (subst O D m k s) (subst O D n k s)
-    | Lambda T n β‡’ Lambda O D T (subst O D n (S k) s)
-    | Vec T v β‡’ Vec O D T (map ?? (Ξ»x. subst O D x k s) v) 
-    ].
-(* notation "hvbox(M break [ k β‰ N ])" 
-   non associative with precedence 90
-   for @{'Subst1 $M $k $N}. *)
-interpretation "Subst" 'Subst1 M k N = (subst M k N). 
-
-(*
-lemma subst_rel1: βˆ€O,D,A.βˆ€k,i. i < k β†’ 
-  (Rel O D i) [k β‰ A] = Rel O D i.
-#A #k #i normalize #ltik >(lt_to_leb_false β€¦ ltik) //
-qed.
-
-lemma subst_rel2: βˆ€O,D, A.βˆ€k. 
-  (Rel k) [k β‰ A] = lift A 0 k.
-#A #k normalize >(le_to_leb_true k k) // >(eq_to_eqb_true β€¦ (refl β€¦)) //
-qed.
-
-lemma subst_rel3: βˆ€A.βˆ€k,i. k < i β†’ 
-  (Rel i) [k β‰ A] = Rel (i-1).
-#A #k #i normalize #ltik >(le_to_leb_true k i) /2/ 
->(not_eq_to_eqb_false k i) // @lt_to_not_eq //
-qed. *)
-
-
-(* closed terms ????
-let rec closed_k O D (t: T O D) k on t β‰ 
-  match t with 
-    [ Val o a β‡’ True
-    | Rel n β‡’ n < k 
-    | App m n β‡’ (closed_k O D m k) βˆ§ (closed_k O D n k)
-    | Lambda T n β‡’ closed_k O D n (k+1)
-    | Vec T v β‡’ closed_list O D v k
-    ]
-    
-and closed_list O D (l: list (T O D)) k on l β‰
-  match l with
-    [ nil β‡’ True
-    | cons hd tl β‡’ closed_k O D hd k βˆ§ closed_list O D tl k
-    ]
-. *)
-
-inductive is_closed (O:Type[0]) (D:Oβ†’FinSet): nat β†’ T O D β†’ Prop β‰
-| cval : βˆ€k,o,a.is_closed O D k (Val O D o a)
-| crel : βˆ€k,n. n < k β†’ is_closed O D k (Rel O D n)
-| capp : βˆ€k,m,n. is_closed O D k m β†’ is_closed O D k n β†’ 
-           is_closed O D k (App O D m n)
-| clam : βˆ€T,k,m. is_closed O D (S k) m β†’ is_closed O D k (Lambda O D T m)
-| cvec:  βˆ€T,k,v. (βˆ€m. mem ? m v β†’ is_closed O D k m) β†’ 
-           is_closed O D k (Vec O D T v).
-      
-lemma is_closed_rel: βˆ€O,D,n,k.
-  is_closed O D k (Rel O D n) β†’ n < k.
-#O #D #n #k #H inversion H 
-  [#k0 #o #a #eqk #H destruct
-  |#k0 #n0 #ltn0 #eqk #H destruct //
-  |#k0 #M #N #_ #_ #_ #_ #_ #H destruct
-  |#T #k0 #M #_ #_ #_ #H destruct
-  |#T #k0 #v #_ #_ #_ #H destruct
-  ]
-qed.
-  
-lemma is_closed_app: βˆ€O,D,k,M, N.
-  is_closed O D k (App O D M N) β†’ is_closed O D k M βˆ§ is_closed O D k N.
-#O #D #k #M #N #H inversion H 
-  [#k0 #o #a #eqk #H destruct
-  |#k0 #n0 #ltn0 #eqk #H destruct 
-  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct % //
-  |#T #k0 #M #_ #_ #_ #H destruct
-  |#T #k0 #v #_ #_ #_ #H destruct
-  ]
-qed.
-  
-lemma is_closed_lam: βˆ€O,D,k,ty,M.
-  is_closed O D k (Lambda O D ty M) β†’ is_closed O D (S k) M.
-#O #D #k #ty #M #H inversion H 
-  [#k0 #o #a #eqk #H destruct
-  |#k0 #n0 #ltn0 #eqk #H destruct 
-  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct 
-  |#T #k0 #M1 #HM1 #_ #_ #H1 destruct //
-  |#T #k0 #v #_ #_ #_ #H destruct
-  ]
-qed.
-
-lemma is_closed_vec: βˆ€O,D,k,ty,v.
-  is_closed O D k (Vec O D ty v) β†’ βˆ€m. mem ? m v β†’ is_closed O D k m.
-#O #D #k #ty #M #H inversion H 
-  [#k0 #o #a #eqk #H destruct
-  |#k0 #n0 #ltn0 #eqk #H destruct 
-  |#k0 #M1 #N1 #HM #HN #_ #_ #_ #H1 destruct 
-  |#T #k0 #M1 #HM1 #_ #_ #H1 destruct
-  |#T #k0 #v #Hv #_ #_ #H1 destruct @Hv
-  ]
-qed.
-
-lemma is_closed_S: βˆ€O,D,M,m.
-  is_closed O D m M β†’ is_closed O D (S m) M.
-#O #D #M #m #H elim H //
-  [#k #n0 #Hlt @crel @le_S //
-  |#k #P #Q #HP #HC #H1 #H2 @capp //
-  |#ty #k #P #HP #H1 @clam //
-  |#ty #k #v #Hind #Hv @cvec @Hv
-  ]
-qed.
-
-lemma is_closed_mono: βˆ€O,D,M,m,n. m β‰€ n β†’
-  is_closed O D m M β†’ is_closed O D n M.
-#O #D #M #m #n #lemn elim lemn // #i #j #H #H1 @is_closed_S @H @H1
-qed.
-  
-  
-(*** properties of lift and subst ***)
-
-(*
-lemma lift_0: βˆ€O,D.βˆ€t:T O D.βˆ€k. lift O D t k 0 = t.
-#O #D #t @(T_elim β€¦ t) normalize // 
-  [#n #k cases (leb k n) normalize // 
-  |#o #v #Hind #k @eq_f lapply Hind -Hind elim v // 
-   #hd #tl #Hind #Hind1 normalize @eq_f2 
-    [@Hind1 %1 //|@Hind #x #Hx @Hind1 %2 //]
-  ]
-qed.
-
-lemma lift_closed: βˆ€O,D.βˆ€t:T O D.βˆ€k,p. 
-  is_closed O D k t β†’ lift O D t k p = t.
-#O #D #t @(T_elim β€¦ t) normalize // 
-  [#n #k #p #H >(not_le_to_leb_false β€¦ (lt_to_not_le β€¦ (is_closed_rel β€¦ H))) //
-  |#M #N #HindM #HindN #k #p #H lapply (is_closed_app β€¦ H) * #HcM #HcN
-   >(HindM β€¦ HcM) >(HindN β€¦ HcN) //
-  |#ty #M #HindM #k #p #H lapply (is_closed_lam β€¦ H) -H #H >(HindM β€¦ H) //
-  |#ty #v #HindM #k #p #H lapply (is_closed_vec β€¦ H) -H #H @eq_f 
-   cut (βˆ€m. mem ? m v β†’ lift O D m k p = m)
-    [#m #Hmem @HindM [@Hmem | @H @Hmem]] -HindM
-   elim v // #a #tl #Hind #H1 normalize @eq_f2
-    [@H1 %1 //|@Hind #m #Hmem @H1 %2 @Hmem]
-  ]
-qed.  
-
-*)
-
-lemma subst_closed: βˆ€O,D,M,N,k,i. k β‰€ i β†’ 
-  is_closed O D k M β†’ subst O D M i N = M.
-#O #D #M @(T_elim β€¦ M)
-  [#o #a normalize //
-  |#n #N #k #j #Hlt #Hc lapply (is_closed_rel β€¦ Hc) #Hnk normalize 
-   >not_le_to_leb_false [2:@lt_to_not_le @(lt_to_le_to_lt β€¦ Hnk Hlt)] //
-  |#P #Q #HindP #HindQ #N #k #i #ltki #Hc lapply (is_closed_app β€¦ Hc) * 
-   #HcP #HcQ normalize >(HindP β€¦ ltki HcP) >(HindQ β€¦ ltki HcQ) //
-  |#ty #P #HindP #N #k #i #ltki #Hc lapply (is_closed_lam β€¦ Hc)  
-   #HcP normalize >(HindP β€¦ HcP) // @le_S_S @ltki
-  |#ty #v #Hindv #N #k #i #ltki #Hc lapply (is_closed_vec β€¦ Hc)  
-   #Hcv normalize @eq_f 
-   cut (βˆ€m:T O D.mem (T O D) m vβ†’ subst O D m i N=m)
-    [#m #Hmem @(Hindv β€¦ Hmem N β€¦ ltki) @Hcv @Hmem] 
-   elim v // #a #tl #Hind #H normalize @eq_f2
-    [@H %1 //| @Hind #Hmem #Htl @H %2 @Htl]
-  ]
-qed.
-
-lemma subst_lemma:  βˆ€O,D,A,B,C,k,i. is_closed O D k B β†’ is_closed O D i C β†’
-  subst O D (subst O D A i B) (k+i) C =
-  subst O D (subst O D A (k+S i) C) i B.
-#O #D #A #B #C #k @(T_elim β€¦ A) normalize 
-  [//
-  |#n #i #HBc #HCc @(leb_elim i n) #Hle 
-    [@(eqb_elim i n) #eqni
-      [<eqni >(lt_to_leb_false (k+(S i)) i) // normalize 
-       >(subst_closed β€¦ HBc) // >le_to_leb_true // >eq_to_eqb_true // 
-      |(cut (i < n)) 
-        [cases (le_to_or_lt_eq β€¦ Hle) // #eqin @False_ind /2/] #ltin 
-       (cut (0 < n)) [@(le_to_lt_to_lt β€¦ ltin) //] #posn
-       normalize @(leb_elim (k+i) (n-1)) #nk
-        [@(eqb_elim (k+i) (n-1)) #H normalize
-          [cut (k+(S i) = n); [/2 by S_pred/] #H1
-           >(le_to_leb_true (k+(S i)) n) /2/
-           >(eq_to_eqb_true β€¦ H1) normalize >(subst_closed β€¦ HCc) //
-          |(cut (k+i < n-1)) [@not_eq_to_le_to_lt; //] #Hlt 
-           >(le_to_leb_true (k+(S i)) n) normalize
-            [>(not_eq_to_eqb_false (k+(S i)) n) normalize
-              [>le_to_leb_true [2:@lt_to_le @(le_to_lt_to_lt β€¦ Hlt) //]
-               >not_eq_to_eqb_false // @lt_to_not_eq @(le_to_lt_to_lt β€¦ Hlt) //
-              |@(not_to_not β€¦ H) #Hn /2 by plus_minus/ 
-              ]  
-            |<plus_n_Sm @(lt_to_le_to_lt β€¦ Hlt) //
-            ]
-          ]
-        |>(not_le_to_leb_false (k+(S i)) n) normalize
-          [>(le_to_leb_true β€¦ Hle) >(not_eq_to_eqb_false β€¦ eqni) // 
-          |@(not_to_not β€¦ nk) #H @le_plus_to_minus_r //
-          ]
-        ] 
-      ]
-    |(cut (n < k+i)) [@(lt_to_le_to_lt ? i) /2 by not_le_to_lt/] #ltn 
-     >not_le_to_leb_false [2: @lt_to_not_le @(transitive_lt β€¦ltn) //] normalize 
-     >not_le_to_leb_false [2: @lt_to_not_le //] normalize
-     >(not_le_to_leb_false β€¦ Hle) // 
-    ] 
-  |#M #N #HindM #HindN #i #HBC #HCc @eq_f2 [@HindM // |@HindN //]
-  |#ty #M #HindM #i #HBC #HCc @eq_f >plus_n_Sm >plus_n_Sm @HindM // 
-   @is_closed_S //
-  |#ty #v #Hindv #i #HBC #HCc @eq_f 
-   cut (βˆ€m.mem ? m v β†’ subst O D (subst O D m i B) (k+i) C = 
-          subst O D (subst O D m (k+S i) C) i B)
-    [#m #Hmem @Hindv //] -Hindv elim v normalize [//]
-   #a #tl #Hind #H @eq_f2 [@H %1 // | @Hind #m #Hmem @H %2 //]
-  ]
-qed.
-
-
diff --git a/matita/matita/lib/finite_lambda/typing.ma b/matita/matita/lib/finite_lambda/typing.ma
deleted file mode 100644 (file)
index 791e27d..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-(*
-    ||M||  This file is part of HELM, an Hypertextual, Electronic        
-    ||A||  Library of Mathematics, developed at the Computer Science     
-    ||T||  Department of the University of Bologna, Italy.                     
-    ||I||                                                                 
-    ||T||  
-    ||A||  This file is distributed under the terms of the 
-    \   /  GNU General Public License Version 2        
-     \ /      
-      V_______________________________________________________________ *)
-
-include "finite_lambda/reduction.ma".
-
-
-(****************************************************************)
-
-inductive TJ (O: Type[0]) (D:O β†’ FinSet): list (FType O) β†’ T O D β†’ FType O β†’ Prop β‰
-  | tval: βˆ€G,o,a. TJ O D G (Val O D o a) (atom O o)
-  | trel: βˆ€G1,ty,G2,n. length ? G1 = n β†’ TJ O D (G1@ty::G2) (Rel O D n) ty
-  | tapp: βˆ€G,M,N,ty1,ty2. TJ O D G M (arrow O ty1 ty2) β†’ TJ O D G N ty1 β†’
-      TJ O D G (App O D M N) ty2
-  | tlambda: βˆ€G,M,ty1,ty2. TJ O D (ty1::G) M ty2 β†’ 
-      TJ O D G (Lambda O D ty1 M) (arrow O ty1 ty2)
-  | tvec: βˆ€G,v,ty1,ty2.
-      (|v| = |enum (FinSet_of_FType O D ty1)|) β†’
-      (βˆ€M. mem ? M v β†’ TJ O D G M ty2) β†’
-      TJ O D G (Vec O D ty1 v) (arrow O ty1 ty2).
-
-lemma wt_to_T: βˆ€O,D,G,ty,a.TJ O D G (to_T O D ty a) ty.
-#O #D #G #ty elim ty
-  [#o #a normalize @tval
-  |#ty1 #ty2 #Hind1 #Hind2 normalize * #v #Hv @tvec
-    [<Hv >length_map >length_map //
-    |#M elim v 
-      [normalize @False_ind |#a #v1 #Hind3 * [#eqM >eqM @Hind2 |@Hind3]]
-    ]
-  ]
-qed.
-
-lemma inv_rel: βˆ€O,D,G,n,ty.
-  TJ O D G (Rel O D n) ty β†’ βˆƒG1,G2.|G1|=n∧G=G1@ty::G2.
-#O #D #G #n #ty #Hrel inversion Hrel
-  [#G1 #o #a #_ #H destruct 
-  |#G1 #ty1 #G2 #n1 #H1 #H2 #H3 #H4 destruct %{G1} %{G2} /2/ 
-  |#G1 #M0 #N #ty1 #ty2 #_ #_ #_ #_ #_ #H destruct
-  |#G1 #M0 #ty4 #ty5 #HM0 #_ #_ #H #H1 destruct 
-  |#G1 #v #ty3 #ty4 #_ #_ #_ #_ #H destruct 
-  ]
-qed.
-      
-lemma inv_tlambda: βˆ€O,D,G,M,ty1,ty2,ty3.
-  TJ O D G (Lambda O D ty1 M) (arrow O ty2 ty3) β†’ 
-  ty1 = ty2 βˆ§ TJ O D (ty2::G) M ty3.
-#O #D #G #M #ty1 #ty2 #ty3 #Hlam inversion Hlam
-  [#G1 #o #a #_ #H destruct 
-  |#G1 #ty #G2 #n #_ #_ #H destruct
-  |#G1 #M0 #N #ty1 #ty2 #_ #_ #_ #_ #_ #H destruct
-  |#G1 #M0 #ty4 #ty5 #HM0 #_ #_ #H #H1 destruct % //
-  |#G1 #v #ty3 #ty4 #_ #_ #_ #_ #H destruct 
-  ]
-qed.
-
-lemma inv_tvec: βˆ€O,D,G,v,ty1,ty2,ty3.
-   TJ O D G (Vec O D ty1 v) (arrow O ty2 ty3) β†’
-  (|v| = |enum (FinSet_of_FType O D ty1)|) βˆ§
-  (βˆ€M. mem ? M v β†’ TJ O D G M ty3).
-#O #D #G #v #ty1 #ty2 #ty3 #Hvec inversion Hvec
-  [#G #o #a #_ #H destruct 
-  |#G1 #ty #G2 #n #_ #_ #H destruct
-  |#G1 #M0 #N #ty1 #ty2 #_ #_ #_ #_ #_ #H destruct
-  |#G1 #M0 #ty4 #ty5 #HM0 #_ #_ #H #H1 destruct 
-  |#G1 #v1 #ty4 #ty5 #Hv #Hmem #_ #_ #H #H1 destruct % // @Hmem 
-  ]
-qed.
-
-(* could be generalized *)
-lemma weak_rel: βˆ€O,D,G1,G2,ty1,ty2,n. length ? G1 < n β†’ 
-   TJ O D (G1@G2) (Rel O D n) ty1 β†’
-   TJ O D (G1@ty2::G2) (Rel O D (S n)) ty1.
-#O #D #G1 #G2 #ty1 #ty2 #n #HG1 #Hrel lapply (inv_rel β€¦ Hrel)
-* #G3 * #G4 * #H1 #H2 lapply (compare_append β€¦ H2)
-* #G5 *
-  [* #H3 @False_ind >H3 in HG1; >length_append >H1 #H4
-   @(absurd β€¦ H4) @le_to_not_lt //
-  |* #H3 #H4 >H4 >append_cons <associative_append @trel
-   >length_append >length_append <H1 >H3 >length_append normalize 
-   >plus_n_Sm >associative_plus @eq_f //
-  ]
-qed.
-
-lemma strength_rel: βˆ€O,D,G1,G2,ty1,ty2,n. length ? G1 < n β†’ 
-   TJ O D (G1@ty2::G2) (Rel O D n) ty1 β†’
-   TJ O D (G1@G2) (Rel O D (n-1)) ty1.
-#O #D #G1 #G2 #ty1 #ty2 #n #HG1 #Hrel lapply (inv_rel β€¦ Hrel)
-* #G3 * #G4 * #H1 #H2 lapply (compare_append β€¦ H2)
-* #G5 *
-  [* #H3 @False_ind >H3 in HG1; >length_append >H1 #H4
-   @(absurd β€¦ H4) @le_to_not_lt //
-  |lapply G5 -G5 * 
-    [>append_nil normalize * #H3 #H4 destruct @False_ind @(absurd β€¦ HG1) 
-     @le_to_not_lt //
-    |#ty3 #G5 * #H3 normalize #H4 destruct (H4) <associative_append @trel
-     <H1 >H3 >length_append >length_append normalize <plus_minus_associative //
-    ]
-  ]
-qed.
-
-lemma no_matter: βˆ€O,D,G,N,tyN. 
-  TJ O D G N tyN β†’  βˆ€G1,G2,G3.G=G1@G2 β†’ is_closed O D (|G1|) N β†’
-    TJ O D (G1@G3) N tyN.    
-#O #D #G #N #tyN #HN elim HN -HN -tyN -N -G 
-  [#G #o #a #G1 #G2 #G3 #_ #_ @tval 
-  |#G #ty #G2 #n #HG #G3 #G4 #G5 #H #HNC normalize 
-   lapply (is_closed_rel β€¦ HNC) #Hlt lapply (compare_append β€¦ H) * #G6 *
-    [* #H1 @False_ind @(absurd ? Hlt) @le_to_not_lt <HG >H1 >length_append // 
-    |* cases G6
-      [>append_nil normalize #H1 @False_ind 
-       @(absurd ? Hlt) @le_to_not_lt <HG >H1 //
-      |#ty1 #G7 #H1 normalize #H2 destruct >associative_append @trel //
-      ]
-    ]
-  |#G #M #N #ty1 #ty2 #HM #HN #HindM #HindN #G1 #G2 #G3 
-   #Heq #Hc lapply (is_closed_app β€¦ Hc) -Hc * #HMc #HNc  
-   @(tapp β€¦ (HindM β€¦ Heq HMc) (HindN β€¦ Heq HNc))
-  |#G #M #ty1 #ty2 #HM #HindM #G1 #G2 #G3 #Heq #Hc
-   lapply (is_closed_lam β€¦ Hc) -Hc #HMc 
-   @tlambda @(HindM (ty1::G1) G2) [>Heq // |@HMc]
-  |#G #v #ty1 #ty2 #Hlen #Hv #Hind #G1 #G2 #G3 #H1 #Hc @tvec 
-    [>length_map // 
-    |#M #Hmem @Hind // lapply (is_closed_vec β€¦ Hc) #Hvc @Hvc //
-    ]
-  ]
-qed.
-
-lemma nth_spec: βˆ€A,a,d,l1,l2,n. |l1| = n β†’ nth n A (l1@a::l2) d = a.
-#A #a #d #l1 elim l1 normalize
-  [#l2 #n #Hn <Hn  //
-  |#b #tl #Hind #l2 #m #Hm <Hm normalize @Hind //
-  ]
-qed.
-             
-lemma wt_subst_gen: βˆ€O,D,G,M,tyM. 
-  TJ O D G M tyM β†’ 
-   βˆ€G1,G2,N,tyN.G=(G1@tyN::G2) β†’
-    TJ O D G2 N tyN β†’ is_closed O D 0 N β†’
-     TJ O D (G1@G2) (subst O D M (|G1|) N) tyM.
-#O #D #G #M #tyM #HM elim HM -HM -tyM -M -G
-  [#G #o #a #G1 #G2 #N #tyN #_ #HG #_ normalize @tval
-  |#G #ty #G2 #n #Hlen #G21 #G22 #N #tyN #HG #HN #HNc
-   normalize cases (true_or_false (leb (|G21|) n))
-    [#H >H cases (le_to_or_lt_eq β€¦ (leb_true_to_le β€¦ H))
-      [#ltn >(not_eq_to_eqb_false β€¦ (lt_to_not_eq β€¦ ltn)) normalize
-       lapply (compare_append β€¦ HG) * #G3 *
-        [* #HG1 #HG2 @(strength_rel β€¦ tyN β€¦ ltn) <HG @trel @Hlen
-        |* #HG >HG in ltn; >length_append #ltn @False_ind 
-         @(absurd β€¦ ltn) @le_to_not_lt >Hlen //
-        ] 
-      |#HG21 >(eq_to_eqb_true β€¦ HG21) 
-       cut (ty = tyN) 
-        [<(nth_spec ? ty ty ? G2 β€¦ Hlen) >HG @nth_spec @HG21] #Hty >Hty
-       normalize <HG21 @(no_matter ????? HN []) //
-      ]
-    |#H >H normalize lapply (compare_append β€¦ HG) * #G3 *
-      [* #H1 @False_ind @(absurd ? Hlen) @sym_not_eq @lt_to_not_eq >H1
-       >length_append @(lt_to_le_to_lt n (|G21|)) // @not_le_to_lt
-       @(leb_false_to_not_le β€¦ H) 
-      |cases G3 
-        [>append_nil * #H1 @False_ind @(absurd ? Hlen) <H1 @sym_not_eq
-         @lt_to_not_eq @not_le_to_lt @(leb_false_to_not_le β€¦ H)
-        |#ty2 #G4 * #H1 normalize #H2 destruct >associative_append @trel //
-        ]
-      ]    
-    ]
-  |#G #M #N #ty1 #ty2 #HM #HN #HindM #HindN #G1 #G2 #N0 #tyN0 #eqG
-   #HN0 #Hc normalize @(tapp β€¦ ty1) 
-    [@(HindM β€¦ eqG HN0 Hc) |@(HindN β€¦ eqG HN0 Hc)]
-  |#G #M #ty1 #ty2 #HM #HindM #G1 #G2 #N0 #tyN0 #eqG
-   #HN0 #Hc normalize @(tlambda β€¦ ty1) @(HindM (ty1::G1) β€¦ HN0) // >eqG //
-  |#G #v #ty1 #ty2 #Hlen #Hv #Hind #G1 #G2 #N0 #tyN0 #eqG
-   #HN0 #Hc normalize @(tvec β€¦ ty1) 
-    [>length_map @Hlen
-    |#M #Hmem lapply (mem_map ????? Hmem) * #a * -Hmem #Hmem #eqM <eqM
-     @(Hind β€¦ Hmem β€¦ eqG HN0 Hc) 
-    ]
-  ]
-qed.
-
-lemma wt_subst: βˆ€O,D,M,N,G,ty1,ty2. 
-  TJ O D (ty1::G) M ty2 β†’ 
-  TJ O D G N ty1 β†’ is_closed O D 0 N β†’
-  TJ O D G (subst O D M 0 N) ty2.
-#O #D #M #N #G #ty1 #ty2 #HM #HN #Hc @(wt_subst_gen β€¦(ty1::G) β€¦ [ ] β€¦ HN) //
-qed.
-
-lemma subject_reduction: βˆ€O,D,M,M1,G,ty. 
-  TJ O D G M ty β†’ red O D M M1 β†’ TJ O D G M1 ty.
-#O #D #M #M1 #G #ty #HM lapply M1 -M1 elim HM  -HM -ty -G -M
-  [#G #o #a #M1 #Hval elim (red_val ????? Hval)
-  |#G #ty #G1 #n #_ #M1 #Hrel elim (red_rel ???? Hrel) 
-  |#G #M #N #ty1 #ty2 #HM #HN #HindM #HindN #M1 #Hred inversion Hred
-    [#P #M0 #N0 #Hc #H1 destruct (H1) #HM1 @(wt_subst β€¦ HN) //
-     @(proj2 β€¦ (inv_tlambda β€¦ HM))
-    |#ty #v #a #M0 #Ha #H1 #H2 destruct @(proj2 β€¦ (inv_tvec β€¦ HM))
-     @(assoc_to_mem β€¦ Ha)
-    |#M2 #M3 #N0 #Hredl #_ #H1 destruct (H1) #eqM1 @(tapp β€¦ HN) @HindM @Hredl
-    |#M2 #M3 #N0 #Hredr #_ #H1 destruct (H1) #eqM1 @(tapp β€¦ HM) @HindN @Hredr
-    |#ty #N0 #N1 #_ #_ #H1 destruct (H1)
-    |#ty #M0 #H1 destruct (H1)
-    |#ty #N0 #N1 #v #v1 #_ #_ #H1 destruct (H1)
-    ]
-  |#G #P #ty1 #ty2 #HP #Hind #M1 #Hred lapply(red_lambda ????? Hred) *
-    [* #P1 * #HredP #HM1 >HM1 @tlambda @Hind //
-    |#HM1 >HM1 @tvec // #N #HN lapply(mem_map ????? HN) 
-     * #a * #mema #eqN <eqN -eqN @(wt_subst β€¦HP) // @wt_to_T
-    ]
-  |#G #v #ty1 #ty2 #Hlen #Hv #Hind #M1 #Hred lapply(red_vec ????? Hred)
-   * #N * #N1 * #v1 * #v2 * * #H1 #H2 #H3 >H3 @tvec 
-    [<Hlen >H2 >length_append >length_append @eq_f //
-    |#M2 #Hmem cases (mem_append ???? Hmem) -Hmem #Hmem
-      [@Hv >H2 @mem_append_l1 //
-      |cases Hmem 
-        [#HM2 >HM2 -HM2 @(Hind N β€¦ H1) >H2 @mem_append_l2 %1 //
-        |-Hmem #Hmem @Hv >H2 @mem_append_l2 %2 //
-        ]
-      ]
-    ]
-  ]
-qed.
-    
diff --git a/matita/matita/lib/reverse_complexity/big_O.ma b/matita/matita/lib/reverse_complexity/big_O.ma
deleted file mode 100644 (file)
index 833572e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-
-include "arithmetics/nat.ma".
-include "basics/sets.ma".
-
-(******************************** big O notation ******************************)
-
-(*  O f g means g βˆˆ O(f) *)
-definition O: relation (natβ†’nat) β‰
-  Ξ»f,g. βˆƒc.βˆƒn0.βˆ€n. n0 β‰€ n β†’ g n β‰€ c* (f n).
-  
-lemma O_refl: βˆ€s. O s s.
-#s %{1} %{0} #n #_ >commutative_times <times_n_1 @le_n qed.
-
-lemma O_trans: βˆ€s1,s2,s3. O s2 s1 β†’ O s3 s2 β†’ O s3 s1. 
-#s1 #s2 #s3 * #c1 * #n1 #H1 * #c2 * # n2 #H2 %{(c1*c2)}
-%{(max n1 n2)} #n #Hmax 
-@(transitive_le β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
->associative_times @le_times [//|@H2 @(le_maxr β€¦ Hmax)]
-qed.
-
-lemma sub_O_to_O: βˆ€s1,s2. O s1 βŠ† O s2 β†’ O s2 s1.
-#s1 #s2 #H @H // qed.
-
-lemma O_to_sub_O: βˆ€s1,s2. O s2 s1 β†’ O s1 βŠ† O s2.
-#s1 #s2 #H #g #Hg @(O_trans β€¦ H) // qed. 
-
-lemma le_to_O: βˆ€s1,s2. (βˆ€x.s1 x β‰€ s2 x) β†’ O s2 s1.
-#s1 #s2 #Hle %{1} %{0} #n #_ normalize <plus_n_O @Hle
-qed.
-
-definition sum_f β‰ Ξ»f,g:natβ†’nat.Ξ»n.f n + g n.
-interpretation "function sum" 'plus f g = (sum_f f g).
-
-lemma O_plus: βˆ€f,g,s. O s f β†’ O s g β†’ O s (f+g).
-#f #g #s * #cf * #nf #Hf * #cg * #ng #Hg
-%{(cf+cg)} %{(max nf ng)} #n #Hmax normalize 
->distributive_times_plus_r @le_plus 
-  [@Hf @(le_maxl β€¦ Hmax) |@Hg @(le_maxr β€¦ Hmax) ]
-qed.
-lemma O_plus_l: βˆ€f,s1,s2. O s1 f β†’ O (s1+s2) f.
-#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
-@(transitive_le β€¦ (Os1f n lean)) @le_times //
-qed.
-
-lemma O_plus_r: βˆ€f,s1,s2. O s2 f β†’ O (s1+s2) f.
-#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
-@(transitive_le β€¦ (Os1f n lean)) @le_times //
-qed.
-
-lemma O_absorbl: βˆ€f,g,s. O s f β†’ O f g β†’ O s (g+f).
-#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
-qed.
-
-lemma O_absorbr: βˆ€f,g,s. O s f β†’ O f g β†’ O s (f+g).
-#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
-qed.
-
-lemma O_times_c: βˆ€f,c. O f (Ξ»x:β„•.c*f x).
-#f #c %{c} %{0} //
-qed.
-
-lemma O_ext2: βˆ€f,g,s. O s f β†’ (βˆ€x.f x = g x) β†’ O s g.
-#f #g #s * #c * #a #Osf #eqfg %{c} %{a} #n #lean <eqfg @Osf //
-qed.    
-
-
-definition not_O β‰ Ξ»f,g.βˆ€c,n0.βˆƒn. n0 β‰€ n βˆ§ c* (f n) < g n .
-
-(* this is the only classical result *)
-axiom not_O_def: βˆ€f,g. Β¬ O f g β†’ not_O f g.
-
-(******************************* small O notation *****************************)
-
-(*  o f g means g βˆˆ o(f) *)
-definition o: relation (natβ†’nat) β‰
-  Ξ»f,g.βˆ€c.βˆƒn0.βˆ€n. n0 β‰€ n β†’ c * (g n) < f n.
-  
-lemma o_irrefl: βˆ€s. Β¬ o s s.
-#s % #oss cases (oss 1) #n0 #H @(absurd ? (le_n (s n0))) 
-@lt_to_not_le >(times_n_1 (s n0)) in βŠ’ (?%?); >commutative_times @H //
-qed.
-
-lemma o_trans: βˆ€s1,s2,s3. o s2 s1 β†’ o s3 s2 β†’ o s3 s1. 
-#s1 #s2 #s3 #H1 #H2 #c cases (H1 c) #n1 -H1 #H1 cases (H2 1) #n2 -H2 #H2
-%{(max n1 n2)} #n #Hmax 
-@(transitive_lt β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
->(times_n_1 (s2 n)) in βŠ’ (?%?); >commutative_times @H2 @(le_maxr β€¦ Hmax)
-qed.
diff --git a/matita/matita/lib/reverse_complexity/gap.ma b/matita/matita/lib/reverse_complexity/gap.ma
deleted file mode 100644 (file)
index 2c8b6e9..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-
-include "arithmetics/minimization.ma".
-include "arithmetics/bigops.ma".
-include "arithmetics/pidgeon_hole.ma".
-include "arithmetics/iteration.ma".
-
-(************************** notation for miminimization ***********************)
-
-(* an alternative defintion of minimization 
-definition Min β‰ Ξ»a,f. 
-  \big[min,a]_{i < a | f i} i. *)
-
-notation "ΞΌ_{ ident i < n } p" 
-  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
-
-notation "ΞΌ_{ ident i β‰€ n } p" 
-  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
-  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
-  
-lemma f_min_true: βˆ€f,a,b.
-  (βˆƒi. a β‰€ i βˆ§ i β‰€ b βˆ§ f i = true) β†’ f (ΞΌ_{i βˆˆ[a,b]} (f i)) = true.
-#f #a #b * #i * * #Hil #Hir #Hfi @(f_min_true β€¦ (Ξ»x. f x)) <plus_minus_m_m 
-  [%{i} % // % [@Hil |@le_S_S @Hir]|@le_S @(transitive_le β€¦ Hil Hir)]
-qed.
-
-lemma min_up: βˆ€f,a,b.
-  (βˆƒi. a β‰€ i βˆ§ i β‰€ b βˆ§ f i = true) β†’ ΞΌ_{i βˆˆ[a,b]}(f i) β‰€ b. 
-#f #a #b * #i * * #Hil #Hir #Hfi @le_S_S_to_le
-cut ((S b) = S b - a + a) [@plus_minus_m_m @le_S @(transitive_le β€¦ Hil Hir)]
-#Hcut >Hcut in βŠ’ (??%); @lt_min %{i} % // % [@Hil |<Hcut @le_S_S @Hir]
-qed.
-
-(*************************** Kleene's predicate *******************************)
-
-axiom U: nat β†’ nat β†’nat β†’ option nat.
-
-axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
-  U i x n = Some ? y β†’ U i x m = Some ? y.
-  
-lemma unique_U: βˆ€i,x,n,m,yn,ym.
-  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
-#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
-  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
-  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
-   >Hn #HS destruct (HS) //
-  ]
-qed.
-
-definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y.
-
-notation "〈i,xβŒͺ β†“ r" with precedence 60 for @{terminate $i $x $r}.
-
-lemma terminate_dec: βˆ€i,x,n. βŒ©i,xβŒͺ β†“ n βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ n.
-#i #x #n normalize cases (U i x n)
-  [%2 % * #y #H destruct|#y %1 %{y} //]
-qed. 
-
-definition termb β‰ Ξ»i,x,t. 
-  match U i x t with [None β‡’ false |Some y β‡’ true].
-
-lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ βŒ©i,xβŒͺ β†“ t.
-#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
-qed.    
-
-lemma term_to_termb_true: βˆ€i,x,t. βŒ©i,xβŒͺ β†“ t β†’ termb i x t = true.
-#i #x #t * #y #H normalize >H // 
-qed.    
-
-lemma decidable_test : βˆ€n,x,r,r1.
-       (βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ r1) βˆ¨ 
-       (βˆƒi. i < n βˆ§ (Β¬ βŒ©i,xβŒͺ β†“ r βˆ§ βŒ©i,xβŒͺ β†“ r1)).
-#n #x #r1 #r2
-  cut (βˆ€i0.decidable ((〈i0,xβŒͺ↓r1) βˆ¨ Β¬ βŒ©i0,xβŒͺ β†“ r2)) 
-    [#j @decidable_or [@terminate_dec |@decidable_not @terminate_dec ]] #Hdec
- cases(decidable_forall ? Hdec n) 
-  [#H %1 @H  
-  |#H %2 cases (not_forall_to_exists β€¦ Hdec H) #j * #leji #Hj
-   %{j} % // % 
-    [@(not_to_not β€¦ Hj) #H %1 @H 
-    |cases (terminate_dec j x r2) // #H @False_ind cases Hj -Hj #Hj
-     @Hj %2 @H
-  ]
-qed.
-
-(**************************** the gap theorem *********************************)
-definition gapP β‰ Ξ»n,x,g,r. βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g r.
-
-lemma gapP_def : βˆ€n,x,g,r. 
-  gapP n x g r = βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g r.
-// qed.
-
-lemma upper_bound_aux: βˆ€g,b,n,x. (βˆ€x. x β‰€ g x) β†’ βˆ€k.
-  (βˆƒj.j < k βˆ§
-    (βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ g^j b βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g^(S j) b)) βˆ¨
-  βˆƒl. |l| = k βˆ§ unique ? l βˆ§ βˆ€i. i βˆˆ l β†’ i < n βˆ§ βŒ©i,xβŒͺ β†“ g^k b .
-#g#b #n #x #Hg #k elim k 
-  [%2 %{([])} normalize % [% //|#x @False_ind]
-  |#k0 * 
-    [* #j * #lej #H %1 %{j} % [@le_S // | @H ]
-    |* #l * * #Hlen #Hunique #Hterm
-     cases (decidable_test n x (g^k0 b) (g^(S k0) b))
-      [#Hcase %1 %{k0} % [@le_n | @Hcase]
-      |* #j * #ltjn * #H1 #H2 %2 
-       %{(j::l)} % 
-        [ % [normalize @eq_f @Hlen] whd % // % #H3
-         @(absurd ?? H1) @(proj2 β€¦ (Hterm β€¦)) @H3
-        |#x *
-          [#eqxj >eqxj % // 
-          |#Hmemx cases(Hterm β€¦ Hmemx) #lexn * #y #HU
-           % [@lexn] %{y} @(monotonic_U ?????? HU) @Hg
-          ]
-        ]
-      ]
-    ]
-  ]
-qed.
-       
-lemma upper_bound: βˆ€g,b,n,x. (βˆ€x. x β‰€ g x) β†’ βˆƒr. 
-  (* b β‰€ r βˆ§ r β‰€ g^n b βˆ§ βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬ βŒ©i,xβŒͺ β†“ g r. *)
-  b β‰€ r βˆ§ r β‰€ g^n b βˆ§ gapP n x g r. 
-#g #b #n #x #Hg 
-cases (upper_bound_aux g b n x Hg n)
-  [* #j * #Hj #H %{(g^j b)} % [2: @H] % [@le_iter //]
-   @monotonic_iter2 // @lt_to_le //
-  |* #l * * #Hlen #Hunique #Hterm %{(g^n b)} % 
-    [% [@le_iter // |@le_n]] 
-   #i #lein %1 @(proj2 β€¦ (Hterm ??)) 
-   @(eq_length_to_mem_all β€¦ Hlen Hunique β€¦ lein)
-   #x #memx @(proj1  β€¦ (Hterm ??)) //
-  ]
-qed. 
-
-definition gapb β‰ Ξ»n,x,g,r.
-  \big[andb,true]_{i < n} ((termb i x r) βˆ¨ Β¬(termb i x (g r))). 
-  
-lemma gapb_def : βˆ€n,x,g,r. gapb n x g r =
-  \big[andb,true]_{i < n} ((termb i x r) βˆ¨ Β¬(termb i x (g r))). 
-// qed.
-
-lemma gapb_true_to_gapP : βˆ€n,x,g,r. 
-  gapb n x g r = true β†’ βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬(〈i,xβŒͺ β†“ (g r)).
-#n #x #g #r elim n 
-  [>gapb_def >bigop_Strue //
-   #H #i #lti0 @False_ind @(absurd β€¦ lti0) @le_to_not_lt //
-  |#m #Hind >gapb_def >bigop_Strue //
-   #H #i #leSm cases (le_to_or_lt_eq β€¦ leSm)
-    [#lem @Hind [@(andb_true_r β€¦ H)|@le_S_S_to_le @lem]
-    |#eqi >(injective_S β€¦ eqi) lapply (andb_true_l β€¦ H) -H #H cases (orb_true_l β€¦ H) -H
-      [#H %1 @termb_true_to_term //
-      |#H %2 % #H1 >(term_to_termb_true β€¦  H1) in H; normalize #H destruct
-      ]
-    ]
-  ]
-qed.
-
-lemma gapP_to_gapb_true : βˆ€n,x,g,r. 
-  (βˆ€i. i < n β†’ βŒ©i,xβŒͺ β†“ r βˆ¨ Β¬(〈i,xβŒͺ β†“ (g r))) β†’ gapb n x g r = true. 
-#n #x #g #r elim n //
-#m #Hind #H >gapb_def >bigop_Strue // @true_to_andb_true
-  [cases (H m (le_n β€¦)) 
-    [#H2 @orb_true_r1 @term_to_termb_true //
-    |#H2 @orb_true_r2 @sym_eq @noteq_to_eqnot @sym_not_eq 
-     @(not_to_not β€¦ H2) @termb_true_to_term 
-    ]
-  |@Hind #i0 #lei0 @H @le_S //
-  ]
-qed.
-
-
-(* the gap function *)
-let rec gap g n on n β‰
-  match n with 
-  [ O β‡’ 1
-  | S m β‡’ let b β‰ gap g m in ΞΌ_{i βˆˆ [b,g^n b]} (gapb n n g i)
-  ].
-  
-lemma gapS: βˆ€g,m. 
-  gap g (S m) = 
-    (let b β‰ gap g m in 
-      ΞΌ_{i βˆˆ [b,g^(S m) b]} (gapb (S m) (S m) g i)).
-// qed.
-
-lemma upper_bound_gapb: βˆ€g,m. (βˆ€x. x β‰€ g x) β†’ 
-  βˆƒr:β„•.gap g m β‰€ r βˆ§ r β‰€ g^(S m) (gap g m) βˆ§ gapb (S m) (S m) g r = true.
-#g #m #leg 
-lapply (upper_bound g (gap g m) (S m) (S m) leg) * #r * *
-#H1 #H2 #H3 %{r} % 
-  [% // |@gapP_to_gapb_true @H3]
-qed.
-   
-lemma gapS_true: βˆ€g,m. (βˆ€x. x β‰€g x) β†’ gapb (S m) (S m) g (gap g (S m)) = true.
-#g #m #leg @(f_min_true (gapb (S m) (S m) g)) @upper_bound_gapb //
-qed.
-  
-theorem gap_theorem: βˆ€g,i.(βˆ€x. x β‰€ g x)β†’βˆƒk.βˆ€n.k < n β†’ 
-   βŒ©i,nβŒͺ β†“ (gap g n) βˆ¨ Β¬ βŒ©i,nβŒͺ β†“ (g (gap g n)).
-#g #i #leg %{i} * 
-  [#lti0 @False_ind @(absurd ?? (not_le_Sn_O i) ) //
-  |#m #leim lapply (gapS_true g m leg) #H
-   @(gapb_true_to_gapP β€¦ H) //
-  ]
-qed.
-
-(* an upper bound *)
-
-let rec sigma n β‰ 
-  match n with 
-  [ O β‡’ 0 | S m β‡’ n + sigma m ].
-  
-lemma gap_bound: βˆ€g. (βˆ€x. x β‰€ g x) β†’ (monotonic ? le g) β†’ 
-  βˆ€n.gap g n β‰€ g^(sigma n) 1.
-#g #leg #gmono #n elim n 
-  [normalize //
-  |#m #Hind >gapS @(transitive_le ? (g^(S m) (gap g m)))
-    [@min_up @upper_bound_gapb // 
-    |@(transitive_le ? (g^(S m) (g^(sigma m) 1)))
-      [@monotonic_iter // |>iter_iter >commutative_plus @le_n
-    ]
-  ]
-qed.
-
-lemma gap_bound2: βˆ€g. (βˆ€x. x β‰€ g x) β†’ (monotonic ? le g) β†’ 
-  βˆ€n.gap g n β‰€ g^(n*n) 1.
-#g #leg #gmono #n elim n 
-  [normalize //
-  |#m #Hind >gapS @(transitive_le ? (g^(S m) (gap g m)))
-    [@min_up @upper_bound_gapb // 
-    |@(transitive_le ? (g^(S m) (g^(m*m) 1)))
-      [@monotonic_iter //
-      |>iter_iter @monotonic_iter2 [@leg | normalize <plus_n_Sm @le_S_S //
-    ]
-  ]
-qed.
-
-(*
-axiom universal: βˆƒu.βˆ€i,x,y. 
-  βˆƒn. U u βŒ©i,xβŒͺ n = Some y β†” βˆƒm.U i x m = Some y. *)
-
-   
-
-
-
-
-
-
-
-
-
-
diff --git a/matita/matita/lib/reverse_complexity/hierarchy.ma b/matita/matita/lib/reverse_complexity/hierarchy.ma
deleted file mode 100644 (file)
index a621b55..0000000
+++ /dev/null
@@ -1,565 +0,0 @@
-
-include "arithmetics/nat.ma".
-include "arithmetics/log.ma".
-(* include "arithmetics/ord.ma". *)
-include "arithmetics/bigops.ma".
-include "arithmetics/bounded_quantifiers.ma".
-include "arithmetics/pidgeon_hole.ma".
-include "basics/sets.ma".
-include "basics/types.ma".
-
-(************************************ MAX *************************************)
-notation "Max_{ ident i < n | p } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident i < n } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident j βˆˆ [a,b[ } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-  
-notation "Max_{ ident j βˆˆ [a,b[ | p } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-
-lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
-#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
-  [cases (true_or_false (leb b c )) #lebc >lebc normalize
-    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
-    |>leab //
-    ]
-  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
-   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
-   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
-  ]
-qed.
-
-lemma Max0 : βˆ€n. max 0 n = n.
-// qed.
-
-lemma Max0r : βˆ€n. max n 0 = n.
-#n >commutative_max //
-qed.
-
-definition MaxA β‰ 
-  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
-
-definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
-
-lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
-  f a β‰€  Max_{i < n | p i}(f i).
-#f #p #n #a #ltan #pa 
->(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
-qed.
-
-lemma Max_le: βˆ€f,p,n,b. 
-  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
-#f #p #n elim n #b #H // 
-#b0 #H1 cases (true_or_false (p b)) #Hb
-  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
-  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
-  ]
-qed.
-
-(******************************** big O notation ******************************)
-
-(*  O f g means g βˆˆ O(f) *)
-definition O: relation (natβ†’nat) β‰
-  Ξ»f,g. βˆƒc.βˆƒn0.βˆ€n. n0 β‰€ n β†’ g n β‰€ c* (f n).
-  
-lemma O_refl: βˆ€s. O s s.
-#s %{1} %{0} #n #_ >commutative_times <times_n_1 @le_n qed.
-
-lemma O_trans: βˆ€s1,s2,s3. O s2 s1 β†’ O s3 s2 β†’ O s3 s1. 
-#s1 #s2 #s3 * #c1 * #n1 #H1 * #c2 * # n2 #H2 %{(c1*c2)}
-%{(max n1 n2)} #n #Hmax 
-@(transitive_le β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
->associative_times @le_times [//|@H2 @(le_maxr β€¦ Hmax)]
-qed.
-
-lemma sub_O_to_O: βˆ€s1,s2. O s1 βŠ† O s2 β†’ O s2 s1.
-#s1 #s2 #H @H // qed.
-
-lemma O_to_sub_O: βˆ€s1,s2. O s2 s1 β†’ O s1 βŠ† O s2.
-#s1 #s2 #H #g #Hg @(O_trans β€¦ H) // qed. 
-
-definition sum_f β‰ Ξ»f,g:natβ†’nat.Ξ»n.f n + g n.
-interpretation "function sum" 'plus f g = (sum_f f g).
-
-lemma O_plus: βˆ€f,g,s. O s f β†’ O s g β†’ O s (f+g).
-#f #g #s * #cf * #nf #Hf * #cg * #ng #Hg
-%{(cf+cg)} %{(max nf ng)} #n #Hmax normalize 
->distributive_times_plus_r @le_plus 
-  [@Hf @(le_maxl β€¦ Hmax) |@Hg @(le_maxr β€¦ Hmax) ]
-qed.
-lemma O_plus_l: βˆ€f,s1,s2. O s1 f β†’ O (s1+s2) f.
-#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
-@(transitive_le β€¦ (Os1f n lean)) @le_times //
-qed.
-
-lemma O_plus_r: βˆ€f,s1,s2. O s2 f β†’ O (s1+s2) f.
-#f #s1 #s2 * #c * #a #Os1f %{c} %{a} #n #lean 
-@(transitive_le β€¦ (Os1f n lean)) @le_times //
-qed.
-
-lemma O_absorbl: βˆ€f,g,s. O s f β†’ O f g β†’ O s (g+f).
-#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
-qed.
-
-lemma O_absorbr: βˆ€f,g,s. O s f β†’ O f g β†’ O s (f+g).
-#f #g #s #Osf #Ofg @(O_plus β€¦ Osf) @(O_trans β€¦ Osf) //
-qed.
-
-(* 
-lemma O_ff: βˆ€f,s. O s f β†’ O s (f+f).
-#f #s #Osf /2/ 
-qed. *)
-
-lemma O_ext2: βˆ€f,g,s. O s f β†’ (βˆ€x.f x = g x) β†’ O s g.
-#f #g #s * #c * #a #Osf #eqfg %{c} %{a} #n #lean <eqfg @Osf //
-qed.    
-
-
-definition not_O β‰ Ξ»f,g.βˆ€c,n0.βˆƒn. n0 β‰€ n βˆ§ c* (f n) < g n .
-
-(* this is the only classical result *)
-axiom not_O_def: βˆ€f,g. Β¬ O f g β†’ not_O f g.
-
-(******************************* small O notation *****************************)
-
-(*  o f g means g βˆˆ o(f) *)
-definition o: relation (natβ†’nat) β‰
-  Ξ»f,g.βˆ€c.βˆƒn0.βˆ€n. n0 β‰€ n β†’ c * (g n) < f n.
-  
-lemma o_irrefl: βˆ€s. Β¬ o s s.
-#s % #oss cases (oss 1) #n0 #H @(absurd ? (le_n (s n0))) 
-@lt_to_not_le >(times_n_1 (s n0)) in βŠ’ (?%?); >commutative_times @H //
-qed.
-
-lemma o_trans: βˆ€s1,s2,s3. o s2 s1 β†’ o s3 s2 β†’ o s3 s1. 
-#s1 #s2 #s3 #H1 #H2 #c cases (H1 c) #n1 -H1 #H1 cases (H2 1) #n2 -H2 #H2
-%{(max n1 n2)} #n #Hmax 
-@(transitive_lt β€¦ (H1 ??)) [@(le_maxl β€¦ Hmax)]
->(times_n_1 (s2 n)) in βŠ’ (?%?); >commutative_times @H2 @(le_maxr β€¦ Hmax)
-qed.
-
-
-(*********************************** pairing **********************************) 
-
-axiom pair: nat β†’nat β†’nat.
-axiom fst : nat β†’ nat.
-axiom snd : nat β†’ nat.
-axiom fst_pair: βˆ€a,b. fst (pair a b) = a.
-axiom snd_pair: βˆ€a,b. snd (pair a b) = b. 
-
-interpretation "abstract pair" 'pair f g = (pair f g).
-
-(************************ basic complexity notions ****************************)
-
-(* u is the deterministic configuration relation of the universal machine (one 
-   step) 
-
-axiom u: nat β†’ option nat.
-
-let rec U c n on n β‰ 
-  match n with  
-  [ O β‡’ None ?
-  | S m β‡’ match u c with 
-    [ None β‡’ Some ? c (* halting case *)
-    | Some c1 β‡’ U c1 m
-    ]
-  ].
-lemma halt_U: βˆ€i,n,y. u i = None ? β†’ U i n = Some ? y β†’ y = i.
-#i #n #y #H cases n
-  [normalize #H1 destruct |#m normalize >H normalize #H1 destruct //]
-qed. 
-
-lemma Some_to_halt: βˆ€n,i,y. U i n = Some ? y β†’ u y = None ? .
-#n elim n
-  [#i #y normalize #H destruct (H)
-  |#m #Hind #i #y normalize 
-   cut (u i = None ? βˆ¨ βˆƒc. u i = Some ? c) 
-    [cases (u i) [/2/ | #c %2 /2/ ]] 
-   *[#H >H normalize #H1 destruct (H1) // |* #c #H >H normalize @Hind ]
-  ]
-qed. *)
-
-axiom U: nat β†’ nat β†’ nat β†’ option nat. 
-(*
-lemma monotonici_U: βˆ€y,n,m,i.
-  U i m = Some ? y β†’ U i (n+m) = Some ? y.
-#y #n #m elim m 
-  [#i normalize #H destruct 
-  |#p #Hind #i <plus_n_Sm normalize
-    cut (u i = None ? βˆ¨ βˆƒc. u i = Some ? c) 
-    [cases (u i) [/2/ | #c %2 /2/ ]] 
-   *[#H1 >H1 normalize // |* #c #H >H normalize #H1 @Hind //]
-  ]
-qed. *)
-
-axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
-  U i x n = Some ? y β†’ U i x m = Some ? y.
-(* #i #n #m #y #lenm #H >(plus_minus_m_m m n) // @monotonici_U //
-qed. *)
-
-(* axiom U: nat β†’ nat β†’ option nat. *)
-(* axiom monotonic_U: βˆ€i,n,m,y.n β‰€m β†’
-   U i n = Some ? y β†’ U i m = Some ? y. *)
-  
-lemma unique_U: βˆ€i,x,n,m,yn,ym.
-  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
-#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
-  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
-  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
-   >Hn #HS destruct (HS) //
-  ]
-qed.
-
-definition code_for β‰ Ξ»f,i.βˆ€x.
-  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
-
-definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y.
-notation "[i,x] β†“ r" with precedence 60 for @{terminate $i $x $r}.
-
-definition lang β‰ Ξ»i,x.βˆƒr,y. U i x r = Some ? y βˆ§ 0  < y. 
-
-lemma lang_cf :βˆ€f,i,x. code_for f i β†’ 
-  lang i x β†” βˆƒy.f x = Some ? y βˆ§ 0 < y.
-#f #i #x normalize #H %
-  [* #n * #y * #H1 #posy %{y} % // 
-   cases (H x) -H #m #H <(H (max n m)) [2:@(le_maxr β€¦ n) //]
-   @(monotonic_U β€¦ H1) @(le_maxl β€¦ m) //
-  |cases (H x) -H #m #Hm * #y #Hy %{m} %{y} >Hm // 
-  ]
-qed.
-
-(******************************* complexity classes ***************************)
-
-axiom size: nat β†’ nat.
-axiom of_size: nat β†’ nat.
-
-interpretation "size" 'card n = (size n).
-
-axiom size_of_size: βˆ€n. |of_size n| = n.
-axiom monotonic_size: monotonic ? le size.
-
-axiom of_size_max: βˆ€i,n. |i| = n β†’ i β‰€ of_size n.
-
-axiom size_fst : βˆ€n. |fst n| β‰€ |n|.
-
-definition size_f β‰ Ξ»f,n.Max_{i < S (of_size n) | eqb (|i|) n}|(f i)|.
-
-lemma size_f_def: βˆ€f,n. size_f f n = 
-  Max_{i < S (of_size n) | eqb (|i|) n}|(f i)|.
-// qed.
-
-(*
-definition Max_const : βˆ€f,p,n,a. a < n β†’ p a β†’
-  βˆ€n. f n = g n β†’
-  Max_{i < n | p n}(f n) = *)
-
-lemma size_f_size : βˆ€f,n. size_f (f βˆ˜ size) n = |(f n)|.
-#f #n @le_to_le_to_eq
-  [@Max_le #a #lta #Ha normalize >(eqb_true_to_eq  β€¦ Ha) //
-  |<(size_of_size n) in βŠ’ (?%?); >size_f_def
-   @(le_Max (Ξ»i.|f (|i|)|) ? (S (of_size n)) (of_size n) ??)
-    [@le_S_S // | @eq_to_eqb_true //]
-  ]
-qed.
-
-lemma size_f_id : βˆ€n. size_f (Ξ»x.x) n = n.
-#n @le_to_le_to_eq
-  [@Max_le #a #lta #Ha >(eqb_true_to_eq  β€¦ Ha) //
-  |<(size_of_size n) in βŠ’ (?%?); >size_f_def
-   @(le_Max (Ξ»i.|i|) ? (S (of_size n)) (of_size n) ??)
-    [@le_S_S // | @eq_to_eqb_true //]
-  ]
-qed.
-
-lemma size_f_fst : βˆ€n. size_f fst n β‰€ n.
-#n @Max_le #a #lta #Ha <(eqb_true_to_eq  β€¦ Ha) //
-qed.
-
-(* definition def β‰ Ξ»f:nat β†’ option nat.Ξ»x.βˆƒy. f x = Some ? y.*)
-
-(* C s i means that the complexity of i is O(s) *)
-
-definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ |x| β†’ βˆƒy. 
-  U i x (c*(s(|x|))) = Some ? y.
-
-definition CF β‰ Ξ»s,f.βˆƒi.code_for f i βˆ§ C s i.
-
-lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
-#f #g #s #Hext * #i * #Hcode #HC %{i} %
-  [#x cases (Hcode x) #a #H %{a} <Hext @H | //] 
-qed. 
-
-lemma monotonic_CF: βˆ€s1,s2,f. O s2 s1 β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f * #c1 * #a #H * #i * #Hcodef #HCs1 %{i} % //
-cases HCs1 #c2 * #b #H2 %{(c2*c1)} %{(max a b)} 
-#x #Hmax cases (H2 x ?) [2:@(le_maxr β€¦ Hmax)] #y #Hy
-%{y} @(monotonic_U β€¦Hy) >associative_times @le_times // @H @(le_maxl β€¦ Hmax)
-qed. 
-
-(************************** The diagonal language *****************************)
-
-(* the diagonal language used for the hierarchy theorem *)
-
-definition diag β‰ Ξ»s,i. 
-  U (fst i) i (s (|i|)) = Some ? 0. 
-
-lemma equiv_diag: βˆ€s,i. 
-  diag s i β†” [fst i,i] β†“ s (|i|) βˆ§ Β¬lang (fst i) i.
-#s #i %
-  [whd in βŠ’ (%β†’?); #H % [%{0} //] % * #x * #y *
-   #H1 #Hy cut (0 = y) [@(unique_U β€¦ H H1)] #eqy /2/
-  |* * #y cases y //
-   #y0 #H * #H1 @False_ind @H1 -H1 whd %{(s (|i|))} %{(S y0)} % //
-  ]
-qed.
-
-(* Let us define the characteristic function diag_cf for diag, and prove
-it correctness *)
-
-definition diag_cf β‰ Ξ»s,i.
-  match U (fst i) i (s (|i|)) with
-  [ None β‡’ None ?
-  | Some y β‡’ if (eqb y 0) then (Some ? 1) else (Some ? 0)].
-
-lemma diag_cf_OK: βˆ€s,x. diag s x β†” βˆƒy.diag_cf s x = Some ? y βˆ§ 0 < y.
-#s #x % 
-  [whd in βŠ’ (%β†’?); #H %{1} % // whd in βŠ’ (??%?); >H // 
-  |* #y * whd in βŠ’ (??%?β†’?β†’%); 
-   cases (U (fst x) x (s (|x|))) normalize
-    [#H destruct
-    |#x cases (true_or_false (eqb x 0)) #Hx >Hx 
-      [>(eqb_true_to_eq β€¦ Hx) // 
-      |normalize #H destruct #H @False_ind @(absurd ? H) @lt_to_not_le //  
-      ]
-    ]
-  ]
-qed.
-
-lemma diag_spec: βˆ€s,i. code_for (diag_cf s) i β†’ βˆ€x. lang i x β†” diag s x.
-#s #i #Hcode #x @(iff_trans  β€¦ (lang_cf β€¦ Hcode)) @iff_sym @diag_cf_OK
-qed. 
-
-(******************************************************************************)
-
-lemma absurd1: βˆ€P. iff P (Β¬ P) β†’False.
-#P * #H1 #H2 cut (Β¬P) [% #H2 @(absurd β€¦ H2) @H1 //] 
-#H3 @(absurd ?? H3) @H2 @H3 
-qed.
-
-(* axiom weak_pad : βˆ€a,βˆƒa0.βˆ€n. a0 < n β†’ βˆƒb. |〈a,bβŒͺ| = n. *)
-lemma weak_pad1 :βˆ€n,a.βˆƒb. n β‰€ βŒ©a,bβŒͺ. 
-#n #a 
-cut (βˆ€i.decidable (〈a,iβŒͺ < n))
-  [#i @decidable_le ] 
-   #Hdec cases(decidable_forall (Ξ»b. βŒ©a,bβŒͺ < n) Hdec n)
-  [#H cut (βˆ€i. i < n β†’ βˆƒb. b < n βˆ§ βŒ©a,bβŒͺ = i)
-    [@(injective_to_exists β€¦ H) //]
-   #Hcut %{n} @not_lt_to_le % #Han
-   lapply(Hcut ? Han) * #x * #Hx #Hx2 
-   cut (x = n) [//] #Hxn >Hxn in Hx; /2 by absurd/ 
-  |#H lapply(not_forall_to_exists β€¦ Hdec H) 
-   * #b * #H1 #H2 %{b} @not_lt_to_le @H2
-  ]
-qed. 
-
-lemma pad : βˆ€n,a. βˆƒb. n β‰€ |〈a,bβŒͺ|.
-#n #a cases (weak_pad1 (of_size n) a) #b #Hb 
-%{b} <(size_of_size n) @monotonic_size //
-qed.
-
-lemma o_to_ex: βˆ€s1,s2. o s1 s2 β†’ βˆ€i. C s2 i β†’
-  βˆƒb.[i, βŒ©i,bβŒͺ] β†“ s1 (|〈i,bβŒͺ|).
-#s1 #s2  #H #i * #c * #x0 #H1 
-cases (H c) #n0 #H2 cases (pad (max x0 n0) i) #b #Hmax
-%{b} cases (H1 βŒ©i,bβŒͺ ?)
-  [#z #H3 %{z} @(monotonic_U β€¦ H3) @lt_to_le @H2
-   @(le_maxr β€¦ Hmax)
-  |@(le_maxl β€¦ Hmax)
-  ]
-qed. 
-
-lemma diag1_not_s1: βˆ€s1,s2. o s1 s2 β†’ Β¬ CF s2 (diag_cf s1).
-#s1 #s2 #H1 % * #i * #Hcode_i #Hs2_i 
-cases (o_to_ex  β€¦ H1 ? Hs2_i) #b #H2
-lapply (diag_spec β€¦ Hcode_i) #H3
-@(absurd1 (lang i βŒ©i,bβŒͺ))
-@(iff_trans β€¦ (H3 βŒ©i,bβŒͺ)) 
-@(iff_trans β€¦ (equiv_diag β€¦)) >fst_pair 
-%[* #_ // |#H6 % // ]
-qed.
-
-(******************************************************************************)
-
-definition to_Some β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
-
-definition deopt β‰ Ξ»n. match n with 
-  [ None β‡’ 1
-  | Some n β‡’ n].
-  
-definition opt_comp β‰ Ξ»f,g:nat β†’ option nat. Ξ»x.
-  match g x with 
-  [ None β‡’ None ?
-  | Some y β‡’ f y ].   
-
-(* axiom CFU: βˆ€h,g,s. CF s (to_Some h)  β†’ CF s (to_Some (of_size βˆ˜ g)) β†’ 
-  CF (Slow s) (Ξ»x.U (h x) (g x)). *)
-  
-axiom sU2: nat β†’ nat β†’ nat.
-axiom sU: nat β†’ nat β†’ nat β†’ nat.
-
-(* axiom CFU: CF sU (Ξ»x.U (fst x) (snd x)). *)
-
-axiom CFU_new: βˆ€h,g,f,s. 
-  CF s (to_Some h)  β†’ CF s (to_Some g) β†’ CF s (to_Some f) β†’ 
-  O s (Ξ»x. sU (size_f h x) (size_f g x) (size_f f x)) β†’ 
-  CF s (Ξ»x.U (h x) (g x) (|f x|)).
-    
-lemma CFU: βˆ€h,g,f,s1,s2,s3. 
-  CF s1 (to_Some h)  β†’ CF s2 (to_Some g) β†’ CF s3 (to_Some f) β†’ 
-  CF (Ξ»x. s1 x + s2 x + s3 x + sU (size_f h x) (size_f g x) (size_f f x)) 
-    (Ξ»x.U (h x) (g x) (|f x|)).
-#h #g #f #s1 #s2 #s3 #Hh #Hg #Hf @CFU_new
-  [@(monotonic_CF β€¦ Hh) @O_plus_l @O_plus_l @O_plus_l //
-  |@(monotonic_CF β€¦ Hg) @O_plus_l @O_plus_l @O_plus_r //
-  |@(monotonic_CF β€¦ Hf) @O_plus_l @O_plus_r //
-  |@O_plus_r //
-  ]
-qed.
-    
-axiom monotonic_sU: βˆ€a1,a2,b1,b2,c1,c2. a1 β‰€ a2 β†’ b1 β‰€ b2 β†’ c1 β‰€c2 β†’
-  sU a1 b1 c1 β‰€ sU a2 b2 c2.
-
-axiom superlinear_sU: βˆ€i,x,r. r β‰€ sU i x r.
-
-definition sU_space β‰ Ξ»i,x,r.i+x+r.
-definition sU_time β‰ Ξ»i,x,r.i+x+(i^2)*r*(log 2 r).
-
-(*
-axiom CF_comp: βˆ€f,g,s1, s2. CF s1 f β†’ CF s2 g β†’ 
-  CF (Ξ»x.s2 x + s1 (size (deopt (g x)))) (opt_comp f g).
-
-(* axiom CF_comp: βˆ€f,g,s1, s2. CF s1 f β†’ CF s2 g β†’ 
-  CF (s1 βˆ˜ (Ξ»x. size (deopt (g x)))) (opt_comp f g). *)
-  
-axiom CF_comp_strong: βˆ€f,g,s1,s2. CF s1 f β†’ CF s2 g β†’ 
-  CF (s1 βˆ˜ s2) (opt_comp f g). *)
-
-definition IF β‰ Ξ»b,f,g:nat β†’option nat. Ξ»x.
-  match b x with 
-  [None β‡’ None ?
-  |Some n β‡’ if (eqb n 0) then f x else g x].
-  
-axiom IF_CF_new: βˆ€b,f,g,s. CF s b β†’ CF s f β†’ CF s g β†’ CF s (IF b f g).
-
-lemma IF_CF: βˆ€b,f,g,sb,sf,sg. CF sb b β†’ CF sf f β†’ CF sg g β†’ 
-  CF (Ξ»n. sb n + sf n + sg n) (IF b f g).
-#b #f #g #sb #sf #sg #Hb #Hf #Hg @IF_CF_new
-  [@(monotonic_CF β€¦ Hb) @O_plus_l @O_plus_l //
-  |@(monotonic_CF β€¦ Hf) @O_plus_l @O_plus_r //
-  |@(monotonic_CF β€¦ Hg) @O_plus_r //
-  ]
-qed.
-
-lemma diag_cf_def : βˆ€s.βˆ€i. 
-  diag_cf s i =  
-    IF (Ξ»i.U (fst i) i (|of_size (s (|i|))|)) (Ξ»i.Some ? 1) (Ξ»i.Some ? 0) i.
-#s #i normalize >size_of_size // qed. 
-
-(* and now ... *)
-axiom CF_pair: βˆ€f,g,s. CF s (Ξ»x.Some ? (f x)) β†’ CF s (Ξ»x.Some ? (g x)) β†’ 
-  CF s (Ξ»x.Some ? (pair (f x) (g x))).
-
-axiom CF_fst: βˆ€f,s. CF s (Ξ»x.Some ? (f x)) β†’ CF s (Ξ»x.Some ? (fst (f x))).
-
-definition minimal β‰ Ξ»s. CF s (Ξ»n. Some ? n) βˆ§ βˆ€c. CF s (Ξ»n. Some ? c).
-
-
-(*
-axiom le_snd: βˆ€n. |snd n| β‰€ |n|.
-axiom daemon: βˆ€P:Prop.P. *)
-
-definition constructible β‰ Ξ»s. CF s (Ξ»x.Some ? (of_size (s (|x|)))).
-
-lemma diag_s: βˆ€s. minimal s β†’ constructible s β†’ 
-  CF (Ξ»x.sU x x (s x)) (diag_cf s).
-#s * #Hs_id #Hs_c #Hs_constr 
-cut (O (Ξ»x:β„•.sU x x (s x)) s) [%{1} %{0} #n //]
-#O_sU_s @ext_CF [2: #n @sym_eq @diag_cf_def | skip]
-@IF_CF_new [2,3:@(monotonic_CF β€¦ (Hs_c ?)) // ] 
-@CFU_new
-  [@CF_fst @(monotonic_CF β€¦ Hs_id) //
-  |@(monotonic_CF β€¦ Hs_id) //
-  |@(monotonic_CF β€¦ Hs_constr) //
-  |%{1} %{0} #n #_ >commutative_times <times_n_1
-   @monotonic_sU // >size_f_size >size_of_size //
-  ]
-qed. 
-
-(*
-lemma diag_s: βˆ€s. minimal s β†’ constructible s β†’ 
-  CF (Ξ»x.s x + sU x x (s x)) (diag_cf s).
-#s * #Hs_id #Hs_c #Hs_constr 
-@ext_CF [2: #n @sym_eq @diag_cf_def | skip]
-@IF_CF_new [2,3:@(monotonic_CF β€¦ (Hs_c ?)) @O_plus_l //]
-@CFU_new
-  [@CF_fst @(monotonic_CF β€¦ Hs_id) @O_plus_l //
-  |@(monotonic_CF β€¦ Hs_id) @O_plus_l //
-  |@(monotonic_CF β€¦ Hs_constr) @O_plus_l //
-  |@O_plus_r %{1} %{0} #n #_ >commutative_times <times_n_1
-   @monotonic_sU // >size_f_size >size_of_size //
-  ]
-qed. *)
-
-(* proof with old axioms
-lemma diag_s: βˆ€s. minimal s β†’ constructible s β†’ 
-  CF (Ξ»x.s x + sU x x (s x)) (diag_cf s).
-#s * #Hs_id #Hs_c #Hs_constr 
-@ext_CF [2: #n @sym_eq @diag_cf_def | skip]
-@(monotonic_CF ???? (IF_CF (Ξ»i:β„•.U (pair (fst i) i) (|of_size (s (|i|))|))
-   β€¦ (Ξ»i.s i + s i + s i + (sU (size_f fst i) (size_f (Ξ»i.i) i) (size_f (Ξ»i.of_size (s (|i|))) i))) β€¦ (Hs_c 1) (Hs_c 0) β€¦ ))
-  [2: @CFU [@CF_fst // | // |@Hs_constr]
-  |@(O_ext2 (Ξ»n:β„•.s n+sU (size_f fst n) n (s n) + (s n+s n+s n+s n))) 
-    [2: #i >size_f_size >size_of_size >size_f_id //] 
-   @O_absorbr 
-    [%{1} %{0} #n #_ >commutative_times <times_n_1 @le_plus //
-     @monotonic_sU // 
-    |@O_plus_l @(O_plus β€¦ (O_refl s)) @(O_plus β€¦ (O_refl s)) 
-     @(O_plus β€¦ (O_refl s)) //
-  ]
-qed.
-*)
-
-(*************************** The hierachy theorem *****************************)
-
-(*
-theorem hierarchy_theorem_right: βˆ€s1,s2:natβ†’nat. 
-  O s1 idN β†’ constructible s1 β†’
-    not_O s2 s1 β†’ Β¬ CF s1 βŠ† CF s2.
-#s1 #s2 #Hs1 #monos1 #H % #H1 
-@(absurd β€¦ (CF s2 (diag_cf s1)))
-  [@H1 @diag_s // |@(diag1_not_s1 β€¦ H)]
-qed.
-*)
-
-theorem hierarchy_theorem_left: βˆ€s1,s2:natβ†’nat.
-   O(s1) βŠ† O(s2) β†’ CF s1 βŠ† CF s2.
-#s1 #s2 #HO #f * #i * #Hcode * #c * #a #Hs1_i %{i} % //
-cases (sub_O_to_O β€¦ HO) -HO #c1 * #b #Hs1s2 
-%{(c*c1)} %{(max a b)} #x #lemax 
-cases (Hs1_i x ?) [2: @(le_maxl β€¦lemax)]
-#y #Hy %{y} @(monotonic_U β€¦ Hy) >associative_times
-@le_times // @Hs1s2 @(le_maxr β€¦ lemax)
-qed.
-
diff --git a/matita/matita/lib/reverse_complexity/speed_clean.ma b/matita/matita/lib/reverse_complexity/speed_clean.ma
deleted file mode 100644 (file)
index bfd3d34..0000000
+++ /dev/null
@@ -1,1068 +0,0 @@
-include "basics/types.ma".
-include "arithmetics/minimization.ma".
-include "arithmetics/bigops.ma".
-include "arithmetics/sigma_pi.ma".
-include "arithmetics/bounded_quantifiers.ma".
-include "reverse_complexity/big_O.ma".
-include "basics/core_notation/napart_2.ma".
-
-(************************* notation for minimization *****************************)
-notation "ΞΌ_{ ident i < n } p" 
-  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
-
-notation "ΞΌ_{ ident i β‰€ n } p" 
-  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
-  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
-  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
-  
-(************************************ MAX *************************************)
-notation "Max_{ ident i < n | p } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident i < n } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident j βˆˆ [a,b[ } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-  
-notation "Max_{ ident j βˆˆ [a,b[ | p } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-
-lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
-#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
-  [cases (true_or_false (leb b c )) #lebc >lebc normalize
-    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
-    |>leab //
-    ]
-  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
-   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
-   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
-  ]
-qed.
-
-lemma Max0 : βˆ€n. max 0 n = n.
-// qed.
-
-lemma Max0r : βˆ€n. max n 0 = n.
-#n >commutative_max //
-qed.
-
-definition MaxA β‰ 
-  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
-
-definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
-
-lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
-  f a β‰€  Max_{i < n | p i}(f i).
-#f #p #n #a #ltan #pa 
->(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
-qed.
-
-lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
-  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
-#f #p #n #m #a #lema #ltan #pa 
->(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
-  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
-  |<plus_minus_m_m //
-  |/2 by monotonic_lt_minus_l/
-  ]
-qed.
-
-lemma Max_le: βˆ€f,p,n,b. 
-  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
-#f #p #n elim n #b #H // 
-#b0 #H1 cases (true_or_false (p b)) #Hb
-  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
-  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
-  ]
-qed.
-
-(********************************** pairing ***********************************)
-axiom pair: nat β†’ nat β†’ nat.
-axiom fst : nat β†’ nat.
-axiom snd : nat β†’ nat.
-
-interpretation "abstract pair" 'pair f g = (pair f g). 
-
-axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
-axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
-axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
-
-axiom le_fst : βˆ€p. fst p β‰€ p.
-axiom le_snd : βˆ€p. snd p β‰€ p.
-axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
-
-(************************************* U **************************************)
-axiom U: nat β†’ nat β†’nat β†’ option nat. 
-
-axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
-  U i x n = Some ? y β†’ U i x m = Some ? y.
-  
-lemma unique_U: βˆ€i,x,n,m,yn,ym.
-  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
-#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
-  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
-  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
-   >Hn #HS destruct (HS) //
-  ]
-qed.
-
-definition code_for β‰ Ξ»f,i.βˆ€x.
-  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
-
-definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
-
-notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
-
-lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
-#i #x #n normalize cases (U i x n)
-  [%2 % * #y #H destruct|#y %1 %{y} //]
-qed.
-  
-lemma monotonic_terminate: βˆ€i,x,n,m.
-  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
-#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
-qed.
-
-definition termb β‰ Ξ»i,x,t. 
-  match U i x t with [None β‡’ false |Some y β‡’ true].
-
-lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
-#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
-qed.    
-
-lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
-#i #x #t * #y #H normalize >H // 
-qed.    
-
-definition out β‰ Ξ»i,x,r. 
-  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
-
-definition bool_to_nat: bool β†’ nat β‰ 
-  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
-
-coercion bool_to_nat. 
-
-definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
-
-lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
-#i #x #r #y % normalize
-  [cases (U i x r) normalize 
-    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
-     #H1 destruct
-    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
-     #H1 //
-    ]
-  |#H >H //]
-qed.
-  
-lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
-#i #x #r % normalize
-  [cases (U i x r) normalize //
-   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
-   #H1 destruct
-  |#H >H //]
-qed.
-
-lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
-#i #x #r normalize cases (U i x r) normalize >fst_pair //
-qed.
-
-lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
-#i #x #r normalize cases (U i x r) normalize >snd_pair //
-qed.
-
-(********************************* the speedup ********************************)
-
-definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
-
-lemma min_input_def : βˆ€h,i,x. 
-  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
-// qed.
-
-lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
-#h #i #x #lexi >min_input_def 
-cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
-qed. 
-
-lemma min_input_to_terminate: βˆ€h,i,x. 
-  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
-#h #i #x #Hminx
-cases (decidable_le (S i) x) #Hix
-  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
-    [@termb_true_to_term //
-    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
-     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
-     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
-     #Habs @False_ind /2/
-    ]
-  |@False_ind >min_input_i in Hminx; 
-    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-  ]
-qed.
-
-lemma min_input_to_lt: βˆ€h,i,x. 
-  min_input h i x = x β†’ i < x.
-#h #i #x #Hminx cases (decidable_le (S i) x) // 
-#ltxi @False_ind >min_input_i in Hminx; 
-  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-qed.
-
-lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
-  min_input h i x = x β†’ min_input h i x1 = x.
-#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
-  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
-  |@(min_input_to_lt β€¦ Hminx)
-  |#j #H1 <Hminx @lt_min_to_false //
-  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
-   @(min_input_to_lt β€¦ Hminx)
-  ]
-qed.
-  
-definition g β‰ Ξ»h,u,x. 
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-  
-lemma g_def : βˆ€h,u,x. g h u x =
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-// qed.
-
-lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
-#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
-#eq0 >eq0 normalize // qed.
-
-lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
-  out i x (h (S i) x) < g h 0 x.
-#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
-qed.
-
-(*
-axiom ax1: βˆ€h,i.
-   (βˆƒy.i < y βˆ§ (termb i y (h (S i) y)=true)) βˆ¨ 
-    βˆ€y. i < y β†’ (termb i y (h (S i) y)=false).
-
-lemma eventually_0: βˆ€h,u.βˆƒnu.βˆ€x. nu < x β†’ 
-  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) = 0.
-#h #u elim u
-  [%{0} normalize //
-  |#u0 * #nu0 #Hind cases (ax1 h u0) 
-    [* #x0 * #leu0x0 #Hx0 %{(max nu0 x0)}
-     #x #Hx >bigop_Sfalse
-      [>(minus_n_O u0) @Hind @(le_to_lt_to_lt β€¦ Hx) /2 by le_maxl/
-      |@not_eq_to_eqb_false % #Hf @(absurd (x β‰€ x0)) 
-        [<Hf @true_to_le_min //
-        |@lt_to_not_le @(le_to_lt_to_lt β€¦ Hx) /2 by le_maxl/
-        ]
-      ]
-    |#H %{(max u0 nu0)} #x #Hx >bigop_Sfalse
-      [>(minus_n_O u0) @Hind @(le_to_lt_to_lt β€¦ Hx) @le_maxr //
-      |@not_eq_to_eqb_false >min_input_def
-       >(min_not_exists (Ξ»y.(termb (u0+0) y (h (S (u0+0)) y)))) 
-        [<plus_n_O <plus_n_Sm <plus_minus_m_m 
-          [% #H1 /2/ 
-          |@lt_to_le @(le_to_lt_to_lt β€¦ Hx) @le_maxl //
-          ]
-        |/2 by /
-        ]
-      ]
-    ]
-  ]
-qed.
-
-definition almost_equal β‰ Ξ»f,g:nat β†’ nat. βˆƒnu.βˆ€x. nu < x β†’ f x = g x.
-
-definition almost_equal1 β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
-
-interpretation "almost equal" 'napart f g = (almost_equal f g). 
-
-lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
-#h #u cases (eventually_0 h u) #nu #H %{(max u nu)} #x #Hx @(eq_f ?? S)
->(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA)
-  [>H // @(le_to_lt_to_lt β€¦Hx) /2 by le_maxl/
-  |@lt_to_le @(le_to_lt_to_lt β€¦Hx) /2 by le_maxr/
-  |//
-  ]
-qed. *)
-
-lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
-#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
-  [#H %2 @H | #H %1 @H]  
-qed.
-
-definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
-interpretation "almost equal" 'napart f g = (almost_equal f g). 
-
-lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
-  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
-#h #u elim u
-  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
-  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
-   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
-    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
-      [2: #H %{x} % // <minus_n_O @H]
-     #Hneq0 (* if x is not enough we retry with nu=x *)
-     cases (Hind x) #x1 * #ltx1 
-     >bigop_Sfalse 
-      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
-      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
-        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
-      ]  
-    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
-    ]
-  ]
-qed.
-
-lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
-#h #u @(not_to_not β€¦ (eventually_cancelled h u))
-#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
-%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
-#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
-  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
-qed.
-
-(******************************** Condition 2 *********************************)
-definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
-  
-lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
-#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
-  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
-  |#y #leiy #lty @(lt_min_to_false ????? lty) //
-  ]
-qed.
-
-lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
-#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
-lapply (g_lt β€¦ Hminy)
-lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
-cases (H y) -H #ny #Hy 
-cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
-whd in match (out ???); >termy >Hr  
-#H @(absurd ? H) @le_to_not_lt @le_n
-qed.
-
-
-(********************** complexity ***********************)
-
-(* We assume operations have a minimal structural complexity MSC. 
-For instance, for time complexity, MSC is equal to the size of input.
-For space complexity, MSC is typically 0, since we only measure the
-space required in addition to dimension of the input. *)
-
-axiom MSC : nat β†’ nat.
-axiom MSC_le: βˆ€n. MSC n β‰€ n.
-axiom monotonic_MSC: monotonic ? le MSC.
-axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
-
-(* C s i means i is running in O(s) *)
-definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
-  U i x (c*(s x)) = Some ? y.
-
-(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
-definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
-lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
-#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
-  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
-qed.
-
-(* lemma ext_CF_total : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s (total f) β†’ CF s (total g).
-#f #g #s #Hext * #HO * #i * #Hcode #HC % // %{i} % [2:@HC]
-#x cases (Hcode x) #a #H %{a} #m #leam >(H m leam) normalize @eq_f @Hext
-qed. *)
-
-lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
-   @le_times // 
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
-   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
-  ]
-qed.
-
-lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [@(O_trans β€¦ H) //
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
-   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
-   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
-   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
-  ]
-qed.
-
-lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
-#s #f #c @O_to_CF @O_times_c 
-qed.
-
-(********************************* composition ********************************)
-axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
-  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
-  
-lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
-  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
-#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
-  [#n normalize @Heq | @(CF_comp β€¦ H) //]
-qed.
-
-(*
-lemma CF_comp1: βˆ€f,g,s. CF s (total g) β†’ CF s (total f) β†’ 
-  CF s (total (f βˆ˜ g)).
-#f #g #s #Hg #Hf @(timesc_CF β€¦ 2) @(monotonic_CF β€¦ (CF_comp β€¦ Hg Hf))
-*)
-
-(*
-axiom CF_comp_ext2: βˆ€f,g,h,sf,sh. CF sh (total g) β†’ CF sf (total f) β†’ 
-  (βˆ€x.f(g x) = h x) β†’ 
-  (βˆ€x. sf (g x) β‰€ sh x) β†’ CF sh (total h). 
-
-lemma main_MSC: βˆ€h,f. CF h f β†’ O h (Ξ»x.MSC (f x)). 
-axiom CF_S: CF MSC S.
-axiom CF_fst: CF MSC fst.
-axiom CF_snd: CF MSC snd.
-
-lemma CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
-#h #f #Hf @(CF_comp β€¦ Hf CF_S) @O_plus // @main_MSC //
-qed. 
-
-lemma CF_comp_fst: βˆ€h,f. CF h (total f) β†’ CF h (total (fst βˆ˜ f)).
-#h #f #Hf @(CF_comp β€¦ Hf CF_fst) @O_plus // @main_MSC //
-qed.
-
-lemma CF_comp_snd: βˆ€h,f. CF h (total f) β†’ CF h (total (snd βˆ˜ f)).
-#h #f #Hf @(CF_comp β€¦ Hf CF_snd) @O_plus // @main_MSC //
-qed. *)
-
-definition id β‰ Ξ»x:nat.x.
-
-axiom CF_id: CF MSC id.
-axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
-axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
-axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
-axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
-
-lemma CF_fst: CF MSC fst.
-@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
-qed.
-
-lemma CF_snd: CF MSC snd.
-@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
-qed.
-
-(************************************** eqb ***********************************)
-(* definition btotal β‰ 
-  Ξ»f.Ξ»x:nat. match f x with [true β‡’ Some ? 0 |false β‡’ Some ? 1]. *)
-  
-axiom CF_eqb: βˆ€h,f,g.
-  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
-
-(* 
-axiom eqb_compl2: βˆ€h,f,g.
-  CF2 h (total2 f) β†’ CF2 h (total2 g) β†’ 
-    CF2 h (btotal2 (Ξ»x1,x2.eqb (f x1 x2) (g x1 x2))).
-
-axiom eqb_min_input_compl:βˆ€h,x. 
-   CF (Ξ»i.βˆ‘_{y βˆˆ [S i,S x[ }(h i y))
-   (btotal (Ξ»i.eqb (min_input h i x) x)). *)
-(*********************************** maximum **********************************) 
-
-axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
-  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
-  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
-
-(******************************** minimization ********************************) 
-
-axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
-  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
-  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
-
-(****************************** constructibility ******************************)
-definition constructible β‰ Ξ»s. CF s s.
-
-lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
-  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
-#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
-qed.
-
-lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
-  constructible s1 β†’ constructible s2.
-#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
-qed. 
-
-(********************************* simulation *********************************)
-
-axiom sU : nat β†’ nat. 
-
-axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
-  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
-
-lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
-snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
-#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
-#b1 * #c1 #eqy >eqy -eqy
-cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
-#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
->fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
-qed.
-  
-axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-
-definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
-
-axiom CF_U : CF sU pU_unary.
-
-definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
-definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
-
-lemma CF_termb: CF sU termb_unary. 
-@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
-qed.
-
-lemma CF_out: CF sU out_unary. 
-@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
-qed.
-
-(*
-lemma CF_termb_comp: βˆ€f.CF (sU βˆ˜ f) (termb_unary βˆ˜ f).
-#f @(CF_comp β€¦ CF_termb) *)
-  
-(******************** complexity of g ********************)
-
-definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
-definition auxg β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
-    (out i (snd ux) (h (S i) (snd ux))).
-
-lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
-#h #s #H1 @(CF_compS ? (auxg h) H1) 
-qed.
-
-definition aux1g β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
-    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
-
-lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
-#h #x @same_bigop
-  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
-qed.
-
-lemma compl_g2 : βˆ€h,s1,s2,s. 
-  CF s1
-    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
-  CF s2
-    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
-  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
-  CF s (auxg h).
-#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
-  [#n whd in βŠ’ (??%%); @eq_aux]
-@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
-@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-qed.  
-
-lemma compl_g3 : βˆ€h,s.
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
-  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
-#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
-@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
-qed.
-
-definition min_input_aux β‰ Ξ»h,p.
-  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
-    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
-    
-lemma min_input_eq : βˆ€h,p. 
-    min_input_aux h p  =
-    min_input h (fst p) (snd (snd p)).
-#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
-whd in βŠ’ (??%%); >fst_pair >snd_pair //
-qed.
-
-definition termb_aux β‰ Ξ»h.
-  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
-
-(*
-lemma termb_aux : βˆ€h,p.
-  (Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x))) 
-    βŒ©fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ =
-  termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)) .
-#h #p normalize >fst_pair >snd_pair >fst_pair >snd_pair // 
-qed. *)
-
-lemma compl_g4 : βˆ€h,s1,s.
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
- [#n whd in βŠ’ (??%%); @min_input_eq]
-@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
-  [@CF_compS @CF_fst 
-  |@CF_comp_snd @CF_snd
-  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-(* @(ext_CF (btotal (termb_aux h)))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_compb β€¦ CF_termb) *)
-qed.
-
-(************************* a couple of technical lemmas ***********************)
-lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
-#a elim a // #n #Hind * 
-  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
-qed.
-
-lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
-  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut (b = pred (S b - a + a)) 
-    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
-   generalize in match (S b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] @le_plus 
-      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
-  ]
-qed.
-
-lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
-  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] #Hm 
-     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
-     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
-  ]
-qed. 
-
-lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
-O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
-  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
-qed.
-
-lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
-O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
-qed.
-
-lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
-[@O_plus_l // |@O_plus_r @coroll @Hmono]
-qed.
-
-(*
-axiom compl_g6: βˆ€h.
-  (* constructible (Ξ»x. h (fst x) (snd x)) β†’ *)
-  (CF (Ξ»x. max (MSC x) (sU βŒ©fst (snd x),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ))
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
-*)
-
-lemma compl_g6: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
-#h #hconstr @(ext_CF (termb_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
-  [@CF_comp_pair
-    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
-    |@CF_comp_pair
-      [@(monotonic_CF β€¦ CF_fst) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus
-    [@O_plus
-      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         >distributive_times_plus @le_plus [//]
-         cases (surj_pair b) #c * #d #eqb >eqb
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
-        ]     
-      |@le_to_O #n @sU_le
-      ] 
-    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
-  ]
-qed.
-             
-(* definition faux1 β‰ Ξ»h.
-  (Ξ»x.MSC x + (snd (snd x)-fst x)*(Ξ»x.sU βŒ©fst (snd x),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
-  
-(* complexity of min_input *)
-lemma compl_g7: βˆ€h. 
-  (βˆ€x.MSC x≀h (S (fst (snd x))) (fst x)) β†’
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©fst x,〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hle #hcostr #hmono @(monotonic_CF β€¦ (faux1 h))
-  [#n normalize >fst_pair >snd_pair //]
-@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
->fst_pair >snd_pair @monotonic_sU // @hmono @lexy
-qed.*)
-
-definition big : nat β†’nat β‰ Ξ»x. 
-  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
-
-lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
-#a #b normalize >fst_pair >snd_pair // qed.
-
-lemma le_big : βˆ€x. x β‰€ big x. 
-#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
-[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
-qed.
-
-definition faux2 β‰ Ξ»h.
-  (Ξ»x.MSC x + (snd (snd x)-fst x)*
-    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
-(* proviamo con x *)
-lemma compl_g7: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
-  [#n normalize >fst_pair >snd_pair //]
-@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
->fst_pair >snd_pair @monotonic_sU // @hmono @lexy
-qed.
-
-(* proviamo con x *)
-lemma compl_g71: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
-@le_plus [@monotonic_MSC //]
-cases (decidable_le (fst x) (snd(snd x))) 
-  [#Hle @le_times // @monotonic_sU  
-  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
-  ]
-qed.
-
-(*
-axiom compl_g8: βˆ€h.
-  CF (Ξ»x. sU βŒ©fst x,〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))). *)
-
-definition out_aux β‰ Ξ»h.
-  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
-
-lemma compl_g8: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
-    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
-#h #hconstr @(ext_CF (out_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
-  [@CF_comp_pair
-    [@(monotonic_CF β€¦ CF_fst) #x //
-    |@CF_comp_pair
-      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus 
-    [@O_plus 
-      [@le_to_O #n @sU_le 
-      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
-        ]
-      ]
-    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
-  ]
-qed.
-
-(*
-lemma compl_g81: βˆ€h.
-  (βˆ€x.MSC x≀h (S (fst x)) (snd(snd x))) β†’
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))).
-#h #hle #hconstr @(monotonic_CF ???? (compl_g8 h hle hconstr)) #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦ )) 
-qed. *)
-
-(* axiom daemon : False. *)
-
-lemma compl_g9 : βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
-      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
-   (auxg h).
-#h #hconstr #hmono #hantimono 
-@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
-@O_plus 
-  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
-    [// | @monotonic_MSC // ]]
-@(O_trans β€¦ (coroll2 ??))
-  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
-   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
-   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
-   @le_plus
-    [@le_plus [>big_def >big_def >maxa >maxb //]
-     @le_times 
-      [/2 by monotonic_le_minus_r/ 
-      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
-      ]
-    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
-    ] 
-  |@le_to_O #n >fst_pair >snd_pair
-   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
-   >associative_plus >distributive_times_plus
-   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
-  ]
-qed.
-
-definition sg β‰ Ξ»h,x.
-  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
-
-lemma sg_def : βˆ€h,a,b. 
-  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
-   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
-#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
-qed. 
-
-lemma compl_g11 : βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (sg h) (unary_g h).
-#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
-qed. 
-
-(**************************** closing the argument ****************************)
-
-let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
-  match d with 
-  [ O β‡’ c (* MSC βŒ©βŒ©b,bβŒͺ,〈b,bβŒͺβŒͺ *)
-  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
-     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
-
-lemma h_of_aux_O: βˆ€r,c,b.
-  h_of_aux r c O b  = c.
-// qed.
-
-lemma h_of_aux_S : βˆ€r,c,d,b. 
-  h_of_aux r c (S d) b = 
-    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
-      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
-// qed.
-
-definition h_of β‰ Ξ»r,p. 
-  let m β‰ max (fst p) (snd p) in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
-
-lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
-  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
-#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
-qed.
-
-lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
-  let m β‰ max a b in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
-#r #a #b normalize >fst_pair >snd_pair //
-qed.
-  
-lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
-  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
-#r #Hr #monor #d #d1 lapply d -d elim d1 
-  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
-   >h_of_aux_O >h_of_aux_O  //
-  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
-    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
-     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
-     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
-     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
-    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
-     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
-     @le_plus [@le_times //] 
-      [@monotonic_MSC @le_pair @le_pair //
-      |@le_times [//] @monotonic_sU 
-        [@le_pair // |// |@monor @Hind //]
-      ]
-    ]
-  ]
-qed.
-
-lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
-#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
-cut (max i a β‰€ max i b)
-  [@to_max 
-    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
-#Hmax @(mono_h_of_aux r Hr Hmono) 
-  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
-qed.
-
-axiom h_of_constr : βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  constructible (h_of r).
-
-lemma speed_compl: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
-#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
-  [#x cases (surj_pair x) #a * #b #eqx >eqx 
-   >sg_def cases (decidable_le b a)
-    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
-     <plus_n_O <plus_n_O >h_of_def 
-     cut (max a b = a) 
-      [normalize cases (le_to_or_lt_eq β€¦ leba)
-        [#ltba >(lt_to_leb_false β€¦ ltba) % 
-        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
-     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
-     @monotonic_MSC @le_pair @le_pair //
-    |#ltab >h_of_def >h_of_def
-     cut (max a b = b) 
-      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
-     #Hmax >Hmax 
-     cut (max (S a) b = b) 
-      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
-     #Hmax1 >Hmax1
-     cut (βˆƒd.b - a = S d) 
-       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
-     * #d #eqd >eqd  
-     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
-     cut (b - S d = a) 
-       [@plus_to_minus >commutative_plus @minus_to_plus 
-         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
-     normalize //
-    ]
-  |#n #a #b #leab #lebn >h_of_def >h_of_def
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
-   cut (max b n = n) 
-    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
-   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
-  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
-  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
-    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
-   @(h_of_constr r Hr Hmono Hconstr)
-  ]
-qed.
-
-(* 
-lemma unary_g_def : βˆ€h,i,x. g h i x = unary_g h βŒ©i,xβŒͺ.
-#h #i #x whd in βŠ’ (???%); >fst_pair >snd_pair %
-qed.  *)
-
-(* smn *)
-axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
-
-lemma speed_compl_i: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
-#r #Hr #Hmono #Hconstr #i 
-@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
-  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
-@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
-qed.
-
-theorem pseudo_speedup: 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
-(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
-#r #Hr #Hmono #Hconstr
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
-  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
-  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
- ]
-qed.
-
-theorem pseudo_speedup': 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
-  (* Β¬ O (r βˆ˜ sg) sf. *)
-  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
-#r #Hr #Hmono #Hconstr 
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha
-  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
-  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
-  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
- ]
-qed.
-  
diff --git a/matita/matita/lib/reverse_complexity/speed_def.ma b/matita/matita/lib/reverse_complexity/speed_def.ma
deleted file mode 100644 (file)
index 9812cfb..0000000
+++ /dev/null
@@ -1,922 +0,0 @@
-include "basics/types.ma".
-include "arithmetics/minimization.ma".
-include "arithmetics/bigops.ma".
-include "arithmetics/sigma_pi.ma".
-include "arithmetics/bounded_quantifiers.ma".
-include "reverse_complexity/big_O.ma".
-include "basics/core_notation/napart_2.ma".
-
-(************************* notation for minimization *****************************)
-notation "ΞΌ_{ ident i < n } p" 
-  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
-
-notation "ΞΌ_{ ident i β‰€ n } p" 
-  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
-  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
-  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
-  
-(************************************ MAX *************************************)
-notation "Max_{ ident i < n | p } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident i < n } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident j βˆˆ [a,b[ } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-  
-notation "Max_{ ident j βˆˆ [a,b[ | p } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-
-lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
-#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
-  [cases (true_or_false (leb b c )) #lebc >lebc normalize
-    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
-    |>leab //
-    ]
-  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
-   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
-   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
-  ]
-qed.
-
-lemma Max0 : βˆ€n. max 0 n = n.
-// qed.
-
-lemma Max0r : βˆ€n. max n 0 = n.
-#n >commutative_max //
-qed.
-
-definition MaxA β‰ 
-  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
-
-definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
-
-lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
-  f a β‰€  Max_{i < n | p i}(f i).
-#f #p #n #a #ltan #pa 
->(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
-qed.
-
-lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
-  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
-#f #p #n #m #a #lema #ltan #pa 
->(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
-  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
-  |<plus_minus_m_m //
-  |/2 by monotonic_lt_minus_l/
-  ]
-qed.
-
-lemma Max_le: βˆ€f,p,n,b. 
-  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
-#f #p #n elim n #b #H // 
-#b0 #H1 cases (true_or_false (p b)) #Hb
-  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
-  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
-  ]
-qed.
-
-(********************************** pairing ***********************************)
-axiom pair: nat β†’ nat β†’ nat.
-axiom fst : nat β†’ nat.
-axiom snd : nat β†’ nat.
-
-interpretation "abstract pair" 'pair f g = (pair f g). 
-
-axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
-axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
-axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
-
-axiom le_fst : βˆ€p. fst p β‰€ p.
-axiom le_snd : βˆ€p. snd p β‰€ p.
-axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
-
-(************************************* U **************************************)
-axiom U: nat β†’ nat β†’nat β†’ option nat. 
-
-axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
-  U i x n = Some ? y β†’ U i x m = Some ? y.
-  
-lemma unique_U: βˆ€i,x,n,m,yn,ym.
-  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
-#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
-  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
-  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
-   >Hn #HS destruct (HS) //
-  ]
-qed.
-
-definition code_for β‰ Ξ»f,i.βˆ€x.
-  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
-
-definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
-
-notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
-
-lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
-#i #x #n normalize cases (U i x n)
-  [%2 % * #y #H destruct|#y %1 %{y} //]
-qed.
-  
-lemma monotonic_terminate: βˆ€i,x,n,m.
-  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
-#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
-qed.
-
-definition termb β‰ Ξ»i,x,t. 
-  match U i x t with [None β‡’ false |Some y β‡’ true].
-
-lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
-#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
-qed.    
-
-lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
-#i #x #t * #y #H normalize >H // 
-qed.    
-
-definition out β‰ Ξ»i,x,r. 
-  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
-
-definition bool_to_nat: bool β†’ nat β‰ 
-  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
-
-coercion bool_to_nat. 
-
-definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
-
-lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
-#i #x #r #y % normalize
-  [cases (U i x r) normalize 
-    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
-     #H1 destruct
-    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
-     #H1 //
-    ]
-  |#H >H //]
-qed.
-  
-lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
-#i #x #r % normalize
-  [cases (U i x r) normalize //
-   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
-   #H1 destruct
-  |#H >H //]
-qed.
-
-lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
-#i #x #r normalize cases (U i x r) normalize >fst_pair //
-qed.
-
-lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
-#i #x #r normalize cases (U i x r) normalize >snd_pair //
-qed.
-
-(********************************* the speedup ********************************)
-
-definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
-
-lemma min_input_def : βˆ€h,i,x. 
-  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
-// qed.
-
-lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
-#h #i #x #lexi >min_input_def 
-cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
-qed. 
-
-lemma min_input_to_terminate: βˆ€h,i,x. 
-  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
-#h #i #x #Hminx
-cases (decidable_le (S i) x) #Hix
-  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
-    [@termb_true_to_term //
-    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
-     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
-     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
-     #Habs @False_ind /2/
-    ]
-  |@False_ind >min_input_i in Hminx; 
-    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-  ]
-qed.
-
-lemma min_input_to_lt: βˆ€h,i,x. 
-  min_input h i x = x β†’ i < x.
-#h #i #x #Hminx cases (decidable_le (S i) x) // 
-#ltxi @False_ind >min_input_i in Hminx; 
-  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-qed.
-
-lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
-  min_input h i x = x β†’ min_input h i x1 = x.
-#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
-  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
-  |@(min_input_to_lt β€¦ Hminx)
-  |#j #H1 <Hminx @lt_min_to_false //
-  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
-   @(min_input_to_lt β€¦ Hminx)
-  ]
-qed.
-  
-definition g β‰ Ξ»h,u,x. 
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-  
-lemma g_def : βˆ€h,u,x. g h u x =
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-// qed.
-
-lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
-#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
-#eq0 >eq0 normalize // qed.
-
-lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
-  out i x (h (S i) x) < g h 0 x.
-#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
-qed.
-
-lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
-#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
-  [#H %2 @H | #H %1 @H]  
-qed.
-
-definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
-interpretation "almost equal" 'napart f g = (almost_equal f g). 
-
-lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
-  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
-#h #u elim u
-  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
-  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
-   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
-    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
-      [2: #H %{x} % // <minus_n_O @H]
-     #Hneq0 (* if x is not enough we retry with nu=x *)
-     cases (Hind x) #x1 * #ltx1 
-     >bigop_Sfalse 
-      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
-      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
-        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
-      ]  
-    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
-    ]
-  ]
-qed.
-
-lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
-#h #u @(not_to_not β€¦ (eventually_cancelled h u))
-#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
-%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
-#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
-  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
-qed.
-
-(******************************** Condition 2 *********************************)
-definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
-  
-lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
-#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
-  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
-  |#y #leiy #lty @(lt_min_to_false ????? lty) //
-  ]
-qed.
-
-lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
-#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
-lapply (g_lt β€¦ Hminy)
-lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
-cases (H y) -H #ny #Hy 
-cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
-whd in match (out ???); >termy >Hr  
-#H @(absurd ? H) @le_to_not_lt @le_n
-qed.
-
-
-(********************************* complexity *********************************)
-
-(* We assume operations have a minimal structural complexity MSC. 
-For instance, for time complexity, MSC is equal to the size of input.
-For space complexity, MSC is typically 0, since we only measure the
-space required in addition to dimension of the input. *)
-
-axiom MSC : nat β†’ nat.
-axiom MSC_le: βˆ€n. MSC n β‰€ n.
-axiom monotonic_MSC: monotonic ? le MSC.
-axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
-
-(* C s i means i is running in O(s) *)
-definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
-  U i x (c*(s x)) = Some ? y.
-
-(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
-definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
-lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
-#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
-  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
-qed.
-
-lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
-   @le_times // 
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
-   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
-  ]
-qed.
-
-lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [@(O_trans β€¦ H) //
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
-   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
-   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
-   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
-  ]
-qed.
-
-lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
-#s #f #c @O_to_CF @O_times_c 
-qed.
-
-(********************************* composition ********************************)
-axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
-  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
-  
-lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
-  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
-#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
-  [#n normalize @Heq | @(CF_comp β€¦ H) //]
-qed.
-
-
-(**************************** primitive operations*****************************)
-
-definition id β‰ Ξ»x:nat.x.
-
-axiom CF_id: CF MSC id.
-axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
-axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
-axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
-axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
-
-lemma CF_fst: CF MSC fst.
-@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
-qed.
-
-lemma CF_snd: CF MSC snd.
-@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
-qed.
-
-(************************************** eqb ***********************************)
-  
-axiom CF_eqb: βˆ€h,f,g.
-  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
-
-(*********************************** maximum **********************************) 
-
-axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
-  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
-  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
-
-(******************************** minimization ********************************) 
-
-axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
-  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
-  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
-  
-(************************************* smn ************************************)
-axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
-
-(****************************** constructibility ******************************)
-definition constructible β‰ Ξ»s. CF s s.
-
-lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
-  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
-#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
-qed.
-
-lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
-  constructible s1 β†’ constructible s2.
-#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
-qed. 
-
-(********************************* simulation *********************************)
-
-axiom sU : nat β†’ nat. 
-
-axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
-  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
-
-lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
-snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
-#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
-#b1 * #c1 #eqy >eqy -eqy
-cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
-#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
->fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
-qed.
-  
-axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-
-definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
-
-axiom CF_U : CF sU pU_unary.
-
-definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
-definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
-
-lemma CF_termb: CF sU termb_unary. 
-@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
-qed.
-
-lemma CF_out: CF sU out_unary. 
-@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
-qed.
-
-
-(******************** complexity of g ********************)
-
-definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
-definition auxg β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
-    (out i (snd ux) (h (S i) (snd ux))).
-
-lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
-#h #s #H1 @(CF_compS ? (auxg h) H1) 
-qed.
-
-definition aux1g β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
-    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
-
-lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
-#h #x @same_bigop
-  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
-qed.
-
-lemma compl_g2 : βˆ€h,s1,s2,s. 
-  CF s1
-    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
-  CF s2
-    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
-  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
-  CF s (auxg h).
-#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
-  [#n whd in βŠ’ (??%%); @eq_aux]
-@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
-@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-qed.  
-
-lemma compl_g3 : βˆ€h,s.
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
-  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
-#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
-@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
-qed.
-
-definition min_input_aux β‰ Ξ»h,p.
-  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
-    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
-    
-lemma min_input_eq : βˆ€h,p. 
-    min_input_aux h p  =
-    min_input h (fst p) (snd (snd p)).
-#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
-whd in βŠ’ (??%%); >fst_pair >snd_pair //
-qed.
-
-definition termb_aux β‰ Ξ»h.
-  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
-
-lemma compl_g4 : βˆ€h,s1,s.
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
- [#n whd in βŠ’ (??%%); @min_input_eq]
-@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
-  [@CF_compS @CF_fst 
-  |@CF_comp_snd @CF_snd
-  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-qed.
-
-(************************* a couple of technical lemmas ***********************)
-lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
-#a elim a // #n #Hind * 
-  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
-qed.
-
-lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
-  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut (b = pred (S b - a + a)) 
-    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
-   generalize in match (S b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] @le_plus 
-      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
-  ]
-qed.
-
-lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
-  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] #Hm 
-     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
-     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
-  ]
-qed. 
-
-lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
-O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
-  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
-qed.
-
-lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
-O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
-qed.
-
-(**************************** end of technical lemmas *************************)
-
-lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
-[@O_plus_l // |@O_plus_r @coroll @Hmono]
-qed.
-
-lemma compl_g6: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
-#h #hconstr @(ext_CF (termb_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
-  [@CF_comp_pair
-    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
-    |@CF_comp_pair
-      [@(monotonic_CF β€¦ CF_fst) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus
-    [@O_plus
-      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         >distributive_times_plus @le_plus [//]
-         cases (surj_pair b) #c * #d #eqb >eqb
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
-        ]     
-      |@le_to_O #n @sU_le
-      ] 
-    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
-  ]
-qed.
-
-definition big : nat β†’nat β‰ Ξ»x. 
-  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
-
-lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
-#a #b normalize >fst_pair >snd_pair // qed.
-
-lemma le_big : βˆ€x. x β‰€ big x. 
-#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
-[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
-qed.
-
-definition faux2 β‰ Ξ»h.
-  (Ξ»x.MSC x + (snd (snd x)-fst x)*
-    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
-lemma compl_g7: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
-  [#n normalize >fst_pair >snd_pair //]
-@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
->fst_pair >snd_pair @monotonic_sU // @hmono @lexy
-qed.
-
-lemma compl_g71: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
-@le_plus [@monotonic_MSC //]
-cases (decidable_le (fst x) (snd(snd x))) 
-  [#Hle @le_times // @monotonic_sU  
-  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
-  ]
-qed.
-
-definition out_aux β‰ Ξ»h.
-  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
-
-lemma compl_g8: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
-    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
-#h #hconstr @(ext_CF (out_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
-  [@CF_comp_pair
-    [@(monotonic_CF β€¦ CF_fst) #x //
-    |@CF_comp_pair
-      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus 
-    [@O_plus 
-      [@le_to_O #n @sU_le 
-      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
-        ]
-      ]
-    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
-  ]
-qed.
-
-lemma compl_g9 : βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
-      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
-   (auxg h).
-#h #hconstr #hmono #hantimono 
-@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
-@O_plus 
-  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
-    [// | @monotonic_MSC // ]]
-@(O_trans β€¦ (coroll2 ??))
-  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
-   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
-   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
-   @le_plus
-    [@le_plus [>big_def >big_def >maxa >maxb //]
-     @le_times 
-      [/2 by monotonic_le_minus_r/ 
-      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
-      ]
-    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
-    ] 
-  |@le_to_O #n >fst_pair >snd_pair
-   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
-   >associative_plus >distributive_times_plus
-   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
-  ]
-qed.
-
-definition sg β‰ Ξ»h,x.
-  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
-
-lemma sg_def : βˆ€h,a,b. 
-  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
-   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
-#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
-qed. 
-
-lemma compl_g11 : βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (sg h) (unary_g h).
-#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
-qed. 
-
-(**************************** closing the argument ****************************)
-
-let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
-  match d with 
-  [ O β‡’ c 
-  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
-     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
-
-lemma h_of_aux_O: βˆ€r,c,b.
-  h_of_aux r c O b  = c.
-// qed.
-
-lemma h_of_aux_S : βˆ€r,c,d,b. 
-  h_of_aux r c (S d) b = 
-    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
-      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
-// qed.
-
-definition h_of β‰ Ξ»r,p. 
-  let m β‰ max (fst p) (snd p) in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
-
-lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
-  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
-#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
-qed.
-
-lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
-  let m β‰ max a b in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
-#r #a #b normalize >fst_pair >snd_pair //
-qed.
-  
-lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
-  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
-#r #Hr #monor #d #d1 lapply d -d elim d1 
-  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
-   >h_of_aux_O >h_of_aux_O  //
-  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
-    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
-     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
-     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
-     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
-    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
-     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
-     @le_plus [@le_times //] 
-      [@monotonic_MSC @le_pair @le_pair //
-      |@le_times [//] @monotonic_sU 
-        [@le_pair // |// |@monor @Hind //]
-      ]
-    ]
-  ]
-qed.
-
-lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
-#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
-cut (max i a β‰€ max i b)
-  [@to_max 
-    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
-#Hmax @(mono_h_of_aux r Hr Hmono) 
-  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
-qed.
-
-axiom h_of_constr : βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  constructible (h_of r).
-
-lemma speed_compl: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
-#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
-  [#x cases (surj_pair x) #a * #b #eqx >eqx 
-   >sg_def cases (decidable_le b a)
-    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
-     <plus_n_O <plus_n_O >h_of_def 
-     cut (max a b = a) 
-      [normalize cases (le_to_or_lt_eq β€¦ leba)
-        [#ltba >(lt_to_leb_false β€¦ ltba) % 
-        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
-     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
-     @monotonic_MSC @le_pair @le_pair //
-    |#ltab >h_of_def >h_of_def
-     cut (max a b = b) 
-      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
-     #Hmax >Hmax 
-     cut (max (S a) b = b) 
-      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
-     #Hmax1 >Hmax1
-     cut (βˆƒd.b - a = S d) 
-       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
-     * #d #eqd >eqd  
-     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
-     cut (b - S d = a) 
-       [@plus_to_minus >commutative_plus @minus_to_plus 
-         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
-     normalize //
-    ]
-  |#n #a #b #leab #lebn >h_of_def >h_of_def
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
-   cut (max b n = n) 
-    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
-   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
-  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
-  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
-    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
-   @(h_of_constr r Hr Hmono Hconstr)
-  ]
-qed.
-
-lemma speed_compl_i: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
-#r #Hr #Hmono #Hconstr #i 
-@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
-  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
-@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
-qed.
-
-(**************************** the speedup theorem *****************************)
-theorem pseudo_speedup: 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
-(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
-#r #Hr #Hmono #Hconstr
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
-  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
-  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
- ]
-qed.
-
-theorem pseudo_speedup': 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
-  (* Β¬ O (r βˆ˜ sg) sf. *)
-  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
-#r #Hr #Hmono #Hconstr 
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha
-  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
-  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
-  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
- ]
-qed.
-  
diff --git a/matita/matita/lib/reverse_complexity/speed_new.ma b/matita/matita/lib/reverse_complexity/speed_new.ma
deleted file mode 100644 (file)
index 9812cfb..0000000
+++ /dev/null
@@ -1,922 +0,0 @@
-include "basics/types.ma".
-include "arithmetics/minimization.ma".
-include "arithmetics/bigops.ma".
-include "arithmetics/sigma_pi.ma".
-include "arithmetics/bounded_quantifiers.ma".
-include "reverse_complexity/big_O.ma".
-include "basics/core_notation/napart_2.ma".
-
-(************************* notation for minimization *****************************)
-notation "ΞΌ_{ ident i < n } p" 
-  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
-
-notation "ΞΌ_{ ident i β‰€ n } p" 
-  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
-  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
-  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
-  
-(************************************ MAX *************************************)
-notation "Max_{ ident i < n | p } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident i < n } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident j βˆˆ [a,b[ } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-  
-notation "Max_{ ident j βˆˆ [a,b[ | p } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-
-lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
-#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
-  [cases (true_or_false (leb b c )) #lebc >lebc normalize
-    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
-    |>leab //
-    ]
-  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
-   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
-   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
-  ]
-qed.
-
-lemma Max0 : βˆ€n. max 0 n = n.
-// qed.
-
-lemma Max0r : βˆ€n. max n 0 = n.
-#n >commutative_max //
-qed.
-
-definition MaxA β‰ 
-  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
-
-definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
-
-lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
-  f a β‰€  Max_{i < n | p i}(f i).
-#f #p #n #a #ltan #pa 
->(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
-qed.
-
-lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
-  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
-#f #p #n #m #a #lema #ltan #pa 
->(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
-  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
-  |<plus_minus_m_m //
-  |/2 by monotonic_lt_minus_l/
-  ]
-qed.
-
-lemma Max_le: βˆ€f,p,n,b. 
-  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
-#f #p #n elim n #b #H // 
-#b0 #H1 cases (true_or_false (p b)) #Hb
-  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
-  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
-  ]
-qed.
-
-(********************************** pairing ***********************************)
-axiom pair: nat β†’ nat β†’ nat.
-axiom fst : nat β†’ nat.
-axiom snd : nat β†’ nat.
-
-interpretation "abstract pair" 'pair f g = (pair f g). 
-
-axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
-axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
-axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
-
-axiom le_fst : βˆ€p. fst p β‰€ p.
-axiom le_snd : βˆ€p. snd p β‰€ p.
-axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
-
-(************************************* U **************************************)
-axiom U: nat β†’ nat β†’nat β†’ option nat. 
-
-axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
-  U i x n = Some ? y β†’ U i x m = Some ? y.
-  
-lemma unique_U: βˆ€i,x,n,m,yn,ym.
-  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
-#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
-  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
-  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
-   >Hn #HS destruct (HS) //
-  ]
-qed.
-
-definition code_for β‰ Ξ»f,i.βˆ€x.
-  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
-
-definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
-
-notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
-
-lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
-#i #x #n normalize cases (U i x n)
-  [%2 % * #y #H destruct|#y %1 %{y} //]
-qed.
-  
-lemma monotonic_terminate: βˆ€i,x,n,m.
-  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
-#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
-qed.
-
-definition termb β‰ Ξ»i,x,t. 
-  match U i x t with [None β‡’ false |Some y β‡’ true].
-
-lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
-#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
-qed.    
-
-lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
-#i #x #t * #y #H normalize >H // 
-qed.    
-
-definition out β‰ Ξ»i,x,r. 
-  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
-
-definition bool_to_nat: bool β†’ nat β‰ 
-  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
-
-coercion bool_to_nat. 
-
-definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
-
-lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
-#i #x #r #y % normalize
-  [cases (U i x r) normalize 
-    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
-     #H1 destruct
-    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
-     #H1 //
-    ]
-  |#H >H //]
-qed.
-  
-lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
-#i #x #r % normalize
-  [cases (U i x r) normalize //
-   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
-   #H1 destruct
-  |#H >H //]
-qed.
-
-lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
-#i #x #r normalize cases (U i x r) normalize >fst_pair //
-qed.
-
-lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
-#i #x #r normalize cases (U i x r) normalize >snd_pair //
-qed.
-
-(********************************* the speedup ********************************)
-
-definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
-
-lemma min_input_def : βˆ€h,i,x. 
-  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
-// qed.
-
-lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
-#h #i #x #lexi >min_input_def 
-cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
-qed. 
-
-lemma min_input_to_terminate: βˆ€h,i,x. 
-  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
-#h #i #x #Hminx
-cases (decidable_le (S i) x) #Hix
-  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
-    [@termb_true_to_term //
-    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
-     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
-     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
-     #Habs @False_ind /2/
-    ]
-  |@False_ind >min_input_i in Hminx; 
-    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-  ]
-qed.
-
-lemma min_input_to_lt: βˆ€h,i,x. 
-  min_input h i x = x β†’ i < x.
-#h #i #x #Hminx cases (decidable_le (S i) x) // 
-#ltxi @False_ind >min_input_i in Hminx; 
-  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-qed.
-
-lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
-  min_input h i x = x β†’ min_input h i x1 = x.
-#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
-  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
-  |@(min_input_to_lt β€¦ Hminx)
-  |#j #H1 <Hminx @lt_min_to_false //
-  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
-   @(min_input_to_lt β€¦ Hminx)
-  ]
-qed.
-  
-definition g β‰ Ξ»h,u,x. 
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-  
-lemma g_def : βˆ€h,u,x. g h u x =
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-// qed.
-
-lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
-#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
-#eq0 >eq0 normalize // qed.
-
-lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
-  out i x (h (S i) x) < g h 0 x.
-#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
-qed.
-
-lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
-#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
-  [#H %2 @H | #H %1 @H]  
-qed.
-
-definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
-interpretation "almost equal" 'napart f g = (almost_equal f g). 
-
-lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
-  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
-#h #u elim u
-  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
-  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
-   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
-    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
-      [2: #H %{x} % // <minus_n_O @H]
-     #Hneq0 (* if x is not enough we retry with nu=x *)
-     cases (Hind x) #x1 * #ltx1 
-     >bigop_Sfalse 
-      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
-      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
-        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
-      ]  
-    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
-    ]
-  ]
-qed.
-
-lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
-#h #u @(not_to_not β€¦ (eventually_cancelled h u))
-#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
-%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
-#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
-  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
-qed.
-
-(******************************** Condition 2 *********************************)
-definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
-  
-lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
-#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
-  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
-  |#y #leiy #lty @(lt_min_to_false ????? lty) //
-  ]
-qed.
-
-lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
-#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
-lapply (g_lt β€¦ Hminy)
-lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
-cases (H y) -H #ny #Hy 
-cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
-whd in match (out ???); >termy >Hr  
-#H @(absurd ? H) @le_to_not_lt @le_n
-qed.
-
-
-(********************************* complexity *********************************)
-
-(* We assume operations have a minimal structural complexity MSC. 
-For instance, for time complexity, MSC is equal to the size of input.
-For space complexity, MSC is typically 0, since we only measure the
-space required in addition to dimension of the input. *)
-
-axiom MSC : nat β†’ nat.
-axiom MSC_le: βˆ€n. MSC n β‰€ n.
-axiom monotonic_MSC: monotonic ? le MSC.
-axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
-
-(* C s i means i is running in O(s) *)
-definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
-  U i x (c*(s x)) = Some ? y.
-
-(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
-definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
-lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
-#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
-  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
-qed.
-
-lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
-   @le_times // 
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
-   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
-  ]
-qed.
-
-lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [@(O_trans β€¦ H) //
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
-   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
-   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
-   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
-  ]
-qed.
-
-lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
-#s #f #c @O_to_CF @O_times_c 
-qed.
-
-(********************************* composition ********************************)
-axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
-  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
-  
-lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
-  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
-#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
-  [#n normalize @Heq | @(CF_comp β€¦ H) //]
-qed.
-
-
-(**************************** primitive operations*****************************)
-
-definition id β‰ Ξ»x:nat.x.
-
-axiom CF_id: CF MSC id.
-axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
-axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
-axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
-axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
-
-lemma CF_fst: CF MSC fst.
-@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
-qed.
-
-lemma CF_snd: CF MSC snd.
-@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
-qed.
-
-(************************************** eqb ***********************************)
-  
-axiom CF_eqb: βˆ€h,f,g.
-  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
-
-(*********************************** maximum **********************************) 
-
-axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
-  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
-  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
-
-(******************************** minimization ********************************) 
-
-axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
-  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
-  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
-  
-(************************************* smn ************************************)
-axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
-
-(****************************** constructibility ******************************)
-definition constructible β‰ Ξ»s. CF s s.
-
-lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
-  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
-#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
-qed.
-
-lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
-  constructible s1 β†’ constructible s2.
-#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
-qed. 
-
-(********************************* simulation *********************************)
-
-axiom sU : nat β†’ nat. 
-
-axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
-  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
-
-lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
-snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
-#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
-#b1 * #c1 #eqy >eqy -eqy
-cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
-#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
->fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
-qed.
-  
-axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-
-definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
-
-axiom CF_U : CF sU pU_unary.
-
-definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
-definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
-
-lemma CF_termb: CF sU termb_unary. 
-@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
-qed.
-
-lemma CF_out: CF sU out_unary. 
-@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
-qed.
-
-
-(******************** complexity of g ********************)
-
-definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
-definition auxg β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
-    (out i (snd ux) (h (S i) (snd ux))).
-
-lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
-#h #s #H1 @(CF_compS ? (auxg h) H1) 
-qed.
-
-definition aux1g β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
-    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
-
-lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
-#h #x @same_bigop
-  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
-qed.
-
-lemma compl_g2 : βˆ€h,s1,s2,s. 
-  CF s1
-    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
-  CF s2
-    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
-  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
-  CF s (auxg h).
-#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
-  [#n whd in βŠ’ (??%%); @eq_aux]
-@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
-@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-qed.  
-
-lemma compl_g3 : βˆ€h,s.
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
-  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
-#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
-@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
-qed.
-
-definition min_input_aux β‰ Ξ»h,p.
-  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
-    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
-    
-lemma min_input_eq : βˆ€h,p. 
-    min_input_aux h p  =
-    min_input h (fst p) (snd (snd p)).
-#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
-whd in βŠ’ (??%%); >fst_pair >snd_pair //
-qed.
-
-definition termb_aux β‰ Ξ»h.
-  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
-
-lemma compl_g4 : βˆ€h,s1,s.
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
- [#n whd in βŠ’ (??%%); @min_input_eq]
-@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
-  [@CF_compS @CF_fst 
-  |@CF_comp_snd @CF_snd
-  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-qed.
-
-(************************* a couple of technical lemmas ***********************)
-lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
-#a elim a // #n #Hind * 
-  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
-qed.
-
-lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
-  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut (b = pred (S b - a + a)) 
-    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
-   generalize in match (S b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] @le_plus 
-      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
-  ]
-qed.
-
-lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
-  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] #Hm 
-     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
-     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
-  ]
-qed. 
-
-lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
-O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
-  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
-qed.
-
-lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
-O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
-qed.
-
-(**************************** end of technical lemmas *************************)
-
-lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
-[@O_plus_l // |@O_plus_r @coroll @Hmono]
-qed.
-
-lemma compl_g6: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
-#h #hconstr @(ext_CF (termb_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
-  [@CF_comp_pair
-    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
-    |@CF_comp_pair
-      [@(monotonic_CF β€¦ CF_fst) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus
-    [@O_plus
-      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         >distributive_times_plus @le_plus [//]
-         cases (surj_pair b) #c * #d #eqb >eqb
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
-        ]     
-      |@le_to_O #n @sU_le
-      ] 
-    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
-  ]
-qed.
-
-definition big : nat β†’nat β‰ Ξ»x. 
-  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
-
-lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
-#a #b normalize >fst_pair >snd_pair // qed.
-
-lemma le_big : βˆ€x. x β‰€ big x. 
-#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
-[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
-qed.
-
-definition faux2 β‰ Ξ»h.
-  (Ξ»x.MSC x + (snd (snd x)-fst x)*
-    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
-lemma compl_g7: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
-  [#n normalize >fst_pair >snd_pair //]
-@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
->fst_pair >snd_pair @monotonic_sU // @hmono @lexy
-qed.
-
-lemma compl_g71: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
-@le_plus [@monotonic_MSC //]
-cases (decidable_le (fst x) (snd(snd x))) 
-  [#Hle @le_times // @monotonic_sU  
-  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
-  ]
-qed.
-
-definition out_aux β‰ Ξ»h.
-  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
-
-lemma compl_g8: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
-    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
-#h #hconstr @(ext_CF (out_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
-  [@CF_comp_pair
-    [@(monotonic_CF β€¦ CF_fst) #x //
-    |@CF_comp_pair
-      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus 
-    [@O_plus 
-      [@le_to_O #n @sU_le 
-      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
-        ]
-      ]
-    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
-  ]
-qed.
-
-lemma compl_g9 : βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
-      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
-   (auxg h).
-#h #hconstr #hmono #hantimono 
-@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
-@O_plus 
-  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
-    [// | @monotonic_MSC // ]]
-@(O_trans β€¦ (coroll2 ??))
-  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
-   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
-   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
-   @le_plus
-    [@le_plus [>big_def >big_def >maxa >maxb //]
-     @le_times 
-      [/2 by monotonic_le_minus_r/ 
-      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
-      ]
-    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
-    ] 
-  |@le_to_O #n >fst_pair >snd_pair
-   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
-   >associative_plus >distributive_times_plus
-   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
-  ]
-qed.
-
-definition sg β‰ Ξ»h,x.
-  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
-
-lemma sg_def : βˆ€h,a,b. 
-  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
-   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
-#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
-qed. 
-
-lemma compl_g11 : βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (sg h) (unary_g h).
-#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
-qed. 
-
-(**************************** closing the argument ****************************)
-
-let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
-  match d with 
-  [ O β‡’ c 
-  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
-     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
-
-lemma h_of_aux_O: βˆ€r,c,b.
-  h_of_aux r c O b  = c.
-// qed.
-
-lemma h_of_aux_S : βˆ€r,c,d,b. 
-  h_of_aux r c (S d) b = 
-    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
-      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
-// qed.
-
-definition h_of β‰ Ξ»r,p. 
-  let m β‰ max (fst p) (snd p) in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
-
-lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
-  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
-#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
-qed.
-
-lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
-  let m β‰ max a b in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
-#r #a #b normalize >fst_pair >snd_pair //
-qed.
-  
-lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
-  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
-#r #Hr #monor #d #d1 lapply d -d elim d1 
-  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
-   >h_of_aux_O >h_of_aux_O  //
-  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
-    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
-     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
-     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
-     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
-    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
-     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
-     @le_plus [@le_times //] 
-      [@monotonic_MSC @le_pair @le_pair //
-      |@le_times [//] @monotonic_sU 
-        [@le_pair // |// |@monor @Hind //]
-      ]
-    ]
-  ]
-qed.
-
-lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
-#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
-cut (max i a β‰€ max i b)
-  [@to_max 
-    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
-#Hmax @(mono_h_of_aux r Hr Hmono) 
-  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
-qed.
-
-axiom h_of_constr : βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  constructible (h_of r).
-
-lemma speed_compl: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
-#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
-  [#x cases (surj_pair x) #a * #b #eqx >eqx 
-   >sg_def cases (decidable_le b a)
-    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
-     <plus_n_O <plus_n_O >h_of_def 
-     cut (max a b = a) 
-      [normalize cases (le_to_or_lt_eq β€¦ leba)
-        [#ltba >(lt_to_leb_false β€¦ ltba) % 
-        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
-     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
-     @monotonic_MSC @le_pair @le_pair //
-    |#ltab >h_of_def >h_of_def
-     cut (max a b = b) 
-      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
-     #Hmax >Hmax 
-     cut (max (S a) b = b) 
-      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
-     #Hmax1 >Hmax1
-     cut (βˆƒd.b - a = S d) 
-       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
-     * #d #eqd >eqd  
-     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
-     cut (b - S d = a) 
-       [@plus_to_minus >commutative_plus @minus_to_plus 
-         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
-     normalize //
-    ]
-  |#n #a #b #leab #lebn >h_of_def >h_of_def
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
-   cut (max b n = n) 
-    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
-   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
-  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
-  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
-    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
-   @(h_of_constr r Hr Hmono Hconstr)
-  ]
-qed.
-
-lemma speed_compl_i: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
-#r #Hr #Hmono #Hconstr #i 
-@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
-  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
-@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
-qed.
-
-(**************************** the speedup theorem *****************************)
-theorem pseudo_speedup: 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
-(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
-#r #Hr #Hmono #Hconstr
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
-  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
-  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
- ]
-qed.
-
-theorem pseudo_speedup': 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
-  (* Β¬ O (r βˆ˜ sg) sf. *)
-  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
-#r #Hr #Hmono #Hconstr 
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha
-  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
-  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
-  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
- ]
-qed.
-  
diff --git a/matita/matita/lib/reverse_complexity/toolkit.ma b/matita/matita/lib/reverse_complexity/toolkit.ma
deleted file mode 100644 (file)
index 69fa352..0000000
+++ /dev/null
@@ -1,988 +0,0 @@
-include "basics/types.ma".
-include "arithmetics/minimization.ma".
-include "arithmetics/bigops.ma".
-include "arithmetics/sigma_pi.ma".
-include "arithmetics/bounded_quantifiers.ma".
-include "reverse_complexity/big_O.ma".
-include "basics/core_notation/napart_2.ma".
-
-(************************* notation for minimization *****************************)
-notation "ΞΌ_{ ident i < n } p" 
-  with precedence 80 for @{min $n 0 (Ξ»${ident i}.$p)}.
-
-notation "ΞΌ_{ ident i β‰€ n } p" 
-  with precedence 80 for @{min (S $n) 0 (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b[ } p"
-  with precedence 80 for @{min ($b-$a) $a (Ξ»${ident i}.$p)}.
-  
-notation "ΞΌ_{ ident i βˆˆ [a,b] } p"
-  with precedence 80 for @{min (S $b-$a) $a (Ξ»${ident i}.$p)}.
-  
-(************************************ MAX *************************************)
-notation "Max_{ ident i < n | p } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}. $p) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident i < n } f"
-  with precedence 80
-for @{'bigop $n max 0 (Ξ»${ident i}.true) (Ξ»${ident i}. $f)}.
-
-notation "Max_{ ident j βˆˆ [a,b[ } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.true) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-  
-notation "Max_{ ident j βˆˆ [a,b[ | p } f"
-  with precedence 80
-for @{'bigop ($b-$a) max 0 (Ξ»${ident j}.((Ξ»${ident j}.$p) (${ident j}+$a)))
-  (Ξ»${ident j}.((Ξ»${ident j}.$f)(${ident j}+$a)))}.
-
-lemma Max_assoc: βˆ€a,b,c. max (max a b) c = max a (max b c).
-#a #b #c normalize cases (true_or_false (leb a b)) #leab >leab normalize
-  [cases (true_or_false (leb b c )) #lebc >lebc normalize
-    [>(le_to_leb_true a c) // @(transitive_le ? b) @leb_true_to_le //
-    |>leab //
-    ]
-  |cases (true_or_false (leb b c )) #lebc >lebc normalize //
-   >leab normalize >(not_le_to_leb_false a c) // @lt_to_not_le 
-   @(transitive_lt ? b) @not_le_to_lt @leb_false_to_not_le //
-  ]
-qed.
-
-lemma Max0 : βˆ€n. max 0 n = n.
-// qed.
-
-lemma Max0r : βˆ€n. max n 0 = n.
-#n >commutative_max //
-qed.
-
-definition MaxA β‰ 
-  mk_Aop nat 0 max Max0 Max0r (Ξ»a,b,c.sym_eq β€¦ (Max_assoc a b c)). 
-
-definition MaxAC β‰ mk_ACop nat 0 MaxA commutative_max.
-
-lemma le_Max: βˆ€f,p,n,a. a < n β†’ p a = true β†’
-  f a β‰€  Max_{i < n | p i}(f i).
-#f #p #n #a #ltan #pa 
->(bigop_diff p ? 0 MaxAC f a n) // @(le_maxl β€¦ (le_n ?))
-qed.
-
-lemma le_MaxI: βˆ€f,p,n,m,a. m β‰€ a β†’ a < n β†’ p a = true β†’
-  f a β‰€  Max_{i βˆˆ [m,n[ | p i}(f i).
-#f #p #n #m #a #lema #ltan #pa 
->(bigop_diff ? ? 0 MaxAC (Ξ»i.f (i+m)) (a-m) (n-m)) 
-  [<plus_minus_m_m // @(le_maxl β€¦ (le_n ?))
-  |<plus_minus_m_m //
-  |/2 by monotonic_lt_minus_l/
-  ]
-qed.
-
-lemma Max_le: βˆ€f,p,n,b. 
-  (βˆ€a.a < n β†’ p a = true β†’ f a β‰€ b) β†’ Max_{i < n | p i}(f i) β‰€ b.
-#f #p #n elim n #b #H // 
-#b0 #H1 cases (true_or_false (p b)) #Hb
-  [>bigop_Strue [2:@Hb] @to_max [@H1 // | @H #a #ltab #pa @H1 // @le_S //]
-  |>bigop_Sfalse [2:@Hb] @H #a #ltab #pa @H1 // @le_S //
-  ]
-qed.
-
-(********************************** pairing ***********************************)
-axiom pair: nat β†’ nat β†’ nat.
-axiom fst : nat β†’ nat.
-axiom snd : nat β†’ nat.
-
-interpretation "abstract pair" 'pair f g = (pair f g). 
-
-axiom fst_pair: βˆ€a,b. fst βŒ©a,bβŒͺ = a.
-axiom snd_pair: βˆ€a,b. snd βŒ©a,bβŒͺ = b.
-axiom surj_pair: βˆ€x. βˆƒa,b. x = βŒ©a,bβŒͺ. 
-
-axiom le_fst : βˆ€p. fst p β‰€ p.
-axiom le_snd : βˆ€p. snd p β‰€ p.
-axiom le_pair: βˆ€a,a1,b,b1. a β‰€ a1 β†’ b β‰€ b1 β†’ βŒ©a,bβŒͺ β‰€ βŒ©a1,b1βŒͺ.
-
-(************************************* U **************************************)
-axiom U: nat β†’ nat β†’nat β†’ option nat. 
-
-axiom monotonic_U: βˆ€i,x,n,m,y.n β‰€m β†’
-  U i x n = Some ? y β†’ U i x m = Some ? y.
-  
-lemma unique_U: βˆ€i,x,n,m,yn,ym.
-  U i x n = Some ? yn β†’ U i x m = Some ? ym β†’ yn = ym.
-#i #x #n #m #yn #ym #Hn #Hm cases (decidable_le n m)
-  [#lenm lapply (monotonic_U β€¦ lenm Hn) >Hm #HS destruct (HS) //
-  |#ltmn lapply (monotonic_U β€¦ n β€¦ Hm) [@lt_to_le @not_le_to_lt //]
-   >Hn #HS destruct (HS) //
-  ]
-qed.
-
-definition code_for β‰ Ξ»f,i.βˆ€x.
-  βˆƒn.βˆ€m. n β‰€ m β†’ U i x m = f x.
-
-definition terminate β‰ Ξ»i,x,r. βˆƒy. U i x r = Some ? y. 
-
-notation "{i βŠ™ x} β†“ r" with precedence 60 for @{terminate $i $x $r}. 
-
-lemma terminate_dec: βˆ€i,x,n. {i βŠ™ x} β†“ n βˆ¨ Β¬ {i βŠ™ x} β†“ n.
-#i #x #n normalize cases (U i x n)
-  [%2 % * #y #H destruct|#y %1 %{y} //]
-qed.
-  
-lemma monotonic_terminate: βˆ€i,x,n,m.
-  n β‰€ m β†’ {i βŠ™ x} β†“ n β†’ {i βŠ™ x} β†“ m.
-#i #x #n #m #lenm * #z #H %{z} @(monotonic_U β€¦ H) //
-qed.
-
-definition termb β‰ Ξ»i,x,t. 
-  match U i x t with [None β‡’ false |Some y β‡’ true].
-
-lemma termb_true_to_term: βˆ€i,x,t. termb i x t = true β†’ {i βŠ™ x} β†“ t.
-#i #x #t normalize cases (U i x t) normalize [#H destruct | #y #_ %{y} //]
-qed.    
-
-lemma term_to_termb_true: βˆ€i,x,t. {i βŠ™ x} β†“ t β†’ termb i x t = true.
-#i #x #t * #y #H normalize >H // 
-qed.    
-
-definition out β‰ Ξ»i,x,r. 
-  match U i x r with [ None β‡’ 0 | Some z β‡’ z]. 
-
-definition bool_to_nat: bool β†’ nat β‰ 
-  Ξ»b. match b with [true β‡’ 1 | false β‡’ 0]. 
-
-coercion bool_to_nat. 
-
-definition pU : nat β†’ nat β†’ nat β†’ nat β‰ Ξ»i,x,r.〈termb i x r,out i x rβŒͺ.
-
-lemma pU_vs_U_Some : βˆ€i,x,r,y. pU i x r = βŒ©1,yβŒͺ β†” U i x r = Some ? y.
-#i #x #r #y % normalize
-  [cases (U i x r) normalize 
-    [#H cut (0=1) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H @H] 
-     #H1 destruct
-    |#a #H cut (a=y) [lapply (eq_f β€¦ snd β€¦ H) >snd_pair >snd_pair #H1 @H1] 
-     #H1 //
-    ]
-  |#H >H //]
-qed.
-  
-lemma pU_vs_U_None : βˆ€i,x,r. pU i x r = βŒ©0,0βŒͺ β†” U i x r = None ?.
-#i #x #r % normalize
-  [cases (U i x r) normalize //
-   #a #H cut (1=0) [lapply (eq_f β€¦ fst β€¦ H) >fst_pair >fst_pair #H1 @H1] 
-   #H1 destruct
-  |#H >H //]
-qed.
-
-lemma fst_pU: βˆ€i,x,r. fst (pU i x r) = termb i x r.
-#i #x #r normalize cases (U i x r) normalize >fst_pair //
-qed.
-
-lemma snd_pU: βˆ€i,x,r. snd (pU i x r) = out i x r.
-#i #x #r normalize cases (U i x r) normalize >snd_pair //
-qed.
-
-(********************************* the speedup ********************************)
-
-definition min_input β‰ Ξ»h,i,x. ΞΌ_{y βˆˆ [S i,x] } (termb i y (h (S i) y)).
-
-lemma min_input_def : βˆ€h,i,x. 
-  min_input h i x = min (x -i) (S i) (Ξ»y.termb i y (h (S i) y)).
-// qed.
-
-lemma min_input_i: βˆ€h,i,x. x β‰€ i β†’ min_input h i x = S i.
-#h #i #x #lexi >min_input_def 
-cut (x - i = 0) [@sym_eq /2 by eq_minus_O/] #Hcut //
-qed. 
-
-lemma min_input_to_terminate: βˆ€h,i,x. 
-  min_input h i x = x β†’ {i βŠ™ x} β†“ (h (S i) x).
-#h #i #x #Hminx
-cases (decidable_le (S i) x) #Hix
-  [cases (true_or_false (termb i x (h (S i) x))) #Hcase
-    [@termb_true_to_term //
-    |<Hminx in Hcase; #H lapply (fmin_false (Ξ»x.termb i x (h (S i) x)) (x-i) (S i) H)
-     >min_input_def in Hminx; #Hminx >Hminx in βŠ’ (%β†’?); 
-     <plus_n_Sm <plus_minus_m_m [2: @lt_to_le //]
-     #Habs @False_ind /2/
-    ]
-  |@False_ind >min_input_i in Hminx; 
-    [#eqix >eqix in Hix; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-  ]
-qed.
-
-lemma min_input_to_lt: βˆ€h,i,x. 
-  min_input h i x = x β†’ i < x.
-#h #i #x #Hminx cases (decidable_le (S i) x) // 
-#ltxi @False_ind >min_input_i in Hminx; 
-  [#eqix >eqix in ltxi; * /2/ | @le_S_S_to_le @not_le_to_lt //]
-qed.
-
-lemma le_to_min_input: βˆ€h,i,x,x1. x β‰€ x1 β†’
-  min_input h i x = x β†’ min_input h i x1 = x.
-#h #i #x #x1 #lex #Hminx @(min_exists β€¦ (le_S_S β€¦ lex)) 
-  [@(fmin_true β€¦ (sym_eq β€¦ Hminx)) //
-  |@(min_input_to_lt β€¦ Hminx)
-  |#j #H1 <Hminx @lt_min_to_false //
-  |@plus_minus_m_m @le_S_S @(transitive_le β€¦ lex) @lt_to_le 
-   @(min_input_to_lt β€¦ Hminx)
-  ]
-qed.
-  
-definition g β‰ Ξ»h,u,x. 
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-  
-lemma g_def : βˆ€h,u,x. g h u x =
-  S (max_{i βˆˆ[u,x[ | eqb (min_input h i x) x} (out i x (h (S i) x))).
-// qed.
-
-lemma le_u_to_g_1 : βˆ€h,u,x. x β‰€ u β†’ g h u x = 1.
-#h #u #x #lexu >g_def cut (x-u = 0) [/2 by minus_le_minus_minus_comm/]
-#eq0 >eq0 normalize // qed.
-
-lemma g_lt : βˆ€h,i,x. min_input h i x = x β†’
-  out i x (h (S i) x) < g h 0 x.
-#h #i #x #H @le_S_S @(le_MaxI β€¦ i) /2 by min_input_to_lt/  
-qed.
-
-lemma max_neq0 : βˆ€a,b. max a b β‰  0 β†’ a β‰  0 βˆ¨ b β‰  0.
-#a #b whd in match (max a b); cases (true_or_false (leb a b)) #Hcase >Hcase
-  [#H %2 @H | #H %1 @H]  
-qed.
-
-definition almost_equal β‰ Ξ»f,g:nat β†’ nat. Β¬ βˆ€nu.βˆƒx. nu < x βˆ§ f x β‰  g x.
-interpretation "almost equal" 'napart f g = (almost_equal f g). 
-
-lemma eventually_cancelled: βˆ€h,u.Β¬βˆ€nu.βˆƒx. nu < x βˆ§
-  max_{i βˆˆ [0,u[ | eqb (min_input h i x) x} (out i x (h (S i) x)) β‰  0.
-#h #u elim u
-  [normalize % #H cases (H u) #x * #_ * #H1 @H1 //
-  |#u0 @not_to_not #Hind #nu cases (Hind nu) #x * #ltx
-   cases (true_or_false (eqb (min_input h (u0+O) x) x)) #Hcase 
-    [>bigop_Strue [2:@Hcase] #Hmax cases (max_neq0 β€¦ Hmax) -Hmax
-      [2: #H %{x} % // <minus_n_O @H]
-     #Hneq0 (* if x is not enough we retry with nu=x *)
-     cases (Hind x) #x1 * #ltx1 
-     >bigop_Sfalse 
-      [#H %{x1} % [@transitive_lt //| <minus_n_O @H]
-      |@not_eq_to_eqb_false >(le_to_min_input β€¦ (eqb_true_to_eq β€¦ Hcase))
-        [@lt_to_not_eq @ltx1 | @lt_to_le @ltx1]
-      ]  
-    |>bigop_Sfalse [2:@Hcase] #H %{x} % // <minus_n_O @H
-    ]
-  ]
-qed.
-
-lemma condition_1: βˆ€h,u.g h 0 β‰ˆ g h u.
-#h #u @(not_to_not β€¦ (eventually_cancelled h u))
-#H #nu cases (H (max u nu)) #x * #ltx #Hdiff 
-%{x} % [@(le_to_lt_to_lt β€¦ ltx) @(le_maxr β€¦ (le_n β€¦))] @(not_to_not β€¦ Hdiff) 
-#H @(eq_f ?? S) >(bigop_sumI 0 u x (Ξ»i:β„•.eqb (min_input h i x) x) nat  0 MaxA) 
-  [>H // |@lt_to_le @(le_to_lt_to_lt β€¦ltx) /2 by le_maxr/ |//]
-qed.
-
-(******************************** Condition 2 *********************************)
-definition total β‰ Ξ»f.Ξ»x:nat. Some nat (f x).
-  
-lemma exists_to_exists_min: βˆ€h,i. (βˆƒx. i < x βˆ§ {i βŠ™ x} β†“ h (S i) x) β†’ βˆƒy. min_input h i y = y.
-#h #i * #x * #ltix #Hx %{(min_input h i x)} @min_spec_to_min @found //
-  [@(f_min_true (Ξ»y:β„•.termb i y (h (S i) y))) %{x} % [% // | @term_to_termb_true //]
-  |#y #leiy #lty @(lt_min_to_false ????? lty) //
-  ]
-qed.
-
-lemma condition_2: βˆ€h,i. code_for (total (g h 0)) i β†’ Β¬βˆƒx. i<x βˆ§ {i βŠ™ x} β†“ h (S i) x.
-#h #i whd in βŠ’(%β†’?); #H % #H1 cases (exists_to_exists_min β€¦ H1) #y #Hminy
-lapply (g_lt β€¦ Hminy)
-lapply (min_input_to_terminate β€¦ Hminy) * #r #termy
-cases (H y) -H #ny #Hy 
-cut (r = g h 0 y) [@(unique_U β€¦ ny β€¦ termy) @Hy //] #Hr
-whd in match (out ???); >termy >Hr  
-#H @(absurd ? H) @le_to_not_lt @le_n
-qed.
-
-
-(********************************* complexity *********************************)
-
-(* We assume operations have a minimal structural complexity MSC. 
-For instance, for time complexity, MSC is equal to the size of input.
-For space complexity, MSC is typically 0, since we only measure the
-space required in addition to dimension of the input. *)
-
-axiom MSC : nat β†’ nat.
-axiom MSC_le: βˆ€n. MSC n β‰€ n.
-axiom monotonic_MSC: monotonic ? le MSC.
-axiom MSC_pair: βˆ€a,b. MSC βŒ©a,bβŒͺ β‰€ MSC a + MSC b.
-
-(* C s i means i is running in O(s) *)
-definition C β‰ Ξ»s,i.βˆƒc.βˆƒa.βˆ€x.a β‰€ x β†’ βˆƒy. 
-  U i x (c*(s x)) = Some ? y.
-
-(* C f s means f βˆˆ O(s) where MSC βˆˆO(s) *)
-definition CF β‰ Ξ»s,f.O s MSC βˆ§ βˆƒi.code_for (total f) i βˆ§ C s i.
-lemma ext_CF : βˆ€f,g,s. (βˆ€n. f n = g n) β†’ CF s f β†’ CF s g.
-#f #g #s #Hext * #HO  * #i * #Hcode #HC % // %{i} %
-  [#x cases (Hcode x) #a #H %{a} whd in match (total ??); <Hext @H | //] 
-qed.
-
-lemma monotonic_CF: βˆ€s1,s2,f.(βˆ€x. s1 x β‰€  s2 x) β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [cases HO #c * #a -HO #HO %{c} %{a} #n #lean @(transitive_le β€¦ (HO n lean))
-   @le_times // 
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 %{c} %{a} #n #lean 
-   cases(Hs1 n lean) #y #Hy %{y} @(monotonic_U β€¦Hy) @le_times // 
-  ]
-qed.
-
-lemma O_to_CF: βˆ€s1,s2,f.O s2 s1 β†’ CF s1 f β†’ CF s2 f.
-#s1 #s2 #f #H * #HO * #i * #Hcode #Hs1 % 
-  [@(O_trans β€¦ H) //
-  |%{i} % [//] cases Hs1 #c * #a -Hs1 #Hs1 
-   cases H #c1 * #a1 #Ha1 %{(c*c1)} %{(a+a1)} #n #lean 
-   cases(Hs1 n ?) [2:@(transitive_le β€¦ lean) //] #y #Hy %{y} @(monotonic_U β€¦Hy)
-   >associative_times @le_times // @Ha1 @(transitive_le β€¦ lean) //
-  ]
-qed.
-
-lemma timesc_CF: βˆ€s,f,c.CF (Ξ»x.c*s x) f β†’ CF s f.
-#s #f #c @O_to_CF @O_times_c 
-qed.
-
-(********************************* composition ********************************)
-axiom CF_comp: βˆ€f,g,sf,sg,sh. CF sg g β†’ CF sf f β†’ 
-  O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh (f βˆ˜ g).
-  
-lemma CF_comp_ext: βˆ€f,g,h,sh,sf,sg. CF sg g β†’ CF sf f β†’ 
-  (βˆ€x.f(g x) = h x) β†’ O sh (Ξ»x. sg x + sf (g x)) β†’ CF sh h.
-#f #g #h #sh #sf #sg #Hg #Hf #Heq #H @(ext_CF (f βˆ˜ g))
-  [#n normalize @Heq | @(CF_comp β€¦ H) //]
-qed.
-
-(* primitve recursion *)
-
-let rec prim_rec (k,h:nat β†’nat) n m on n β‰ 
-  match n with 
-  [ O β‡’ k m
-  | S a β‡’ h βŒ©a,〈prim_rec k h a m, mβŒͺβŒͺ].
-  
-lemma prim_rec_S: βˆ€k,h,n,m.
-  prim_rec k h (S n) m = h βŒ©n,〈prim_rec k h n m, mβŒͺβŒͺ.
-// qed.
-
-definition unary_pr β‰ Ξ»k,h,x. prim_rec k h (fst x) (snd x).
-
-let rec prim_rec_compl (k,h,sk,sh:nat β†’nat) n m on n β‰ 
-  match n with 
-  [ O β‡’ sk m
-  | S a β‡’ prim_rec_compl k h sk sh a m + sh (prim_rec k h a m)].
-  
-axiom CF_prim_rec: βˆ€k,h,sk,sh,sf. CF sk k β†’ CF sh h β†’ 
-  O sf (unary_pr sk (Ξ»x. fst (snd x) + sh βŒ©fst x,〈unary_pr k h βŒ©fst x,snd (snd x)βŒͺ,snd (snd x)βŒͺβŒͺ)) 
-   β†’ CF sf (unary_pr k h).
-
-(* falso ????
-lemma prim_rec_O: βˆ€k1,h1,k2,h2. O k1 k2 β†’ O h1 h2 β†’ 
-  O (unary_pr k1 h1) (unary_pr k2 h2).
-#k1 #h1 #k2 #h2 #HO1 #HO2 whd *)
-
-  
-(**************************** primitive operations*****************************)
-
-definition id β‰ Ξ»x:nat.x.
-
-axiom CF_id: CF MSC id.
-axiom CF_compS: βˆ€h,f. CF h f β†’ CF h (S βˆ˜ f).
-axiom CF_comp_fst: βˆ€h,f. CF h f β†’ CF h (fst βˆ˜ f).
-axiom CF_comp_snd: βˆ€h,f. CF h f β†’ CF h (snd βˆ˜ f). 
-axiom CF_comp_pair: βˆ€h,f,g. CF h f β†’ CF h g β†’ CF h (Ξ»x. βŒ©f x,g xβŒͺ). 
-
-lemma CF_fst: CF MSC fst.
-@(ext_CF (fst βˆ˜ id)) [#n //] @(CF_comp_fst β€¦ CF_id)
-qed.
-
-lemma CF_snd: CF MSC snd.
-@(ext_CF (snd βˆ˜ id)) [#n //] @(CF_comp_snd β€¦ CF_id)
-qed.
-
-(************************************** eqb ***********************************)
-  
-axiom CF_eqb: βˆ€h,f,g.
-  CF h f β†’ CF h g β†’ CF h (Ξ»x.eqb (f x) (g x)).
-
-(*********************************** maximum **********************************) 
-
-axiom CF_max: βˆ€a,b.βˆ€p:nat β†’bool.βˆ€f,ha,hb,hp,hf,s.
-  CF ha a β†’ CF hb b β†’ CF hp p β†’ CF hf f β†’ 
-  O s (Ξ»x.ha x + hb x + βˆ‘_{i βˆˆ[a x ,b x[ }(hp βŒ©i,xβŒͺ + hf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.max_{i βˆˆ[a x,b x[ | p βŒ©i,xβŒͺ }(f βŒ©i,xβŒͺ)). 
-
-(******************************** minimization ********************************) 
-
-axiom CF_mu: βˆ€a,b.βˆ€f:nat β†’bool.βˆ€sa,sb,sf,s.
-  CF sa a β†’ CF sb b β†’ CF sf f β†’ 
-  O s (Ξ»x.sa x + sb x + βˆ‘_{i βˆˆ[a x ,S(b x)[ }(sf βŒ©i,xβŒͺ)) β†’
-  CF s (Ξ»x.ΞΌ_{i βˆˆ[a x,b x] }(f βŒ©i,xβŒͺ)).
-  
-(************************************* smn ************************************)
-axiom smn: βˆ€f,s. CF s f β†’ βˆ€x. CF (Ξ»y.s βŒ©x,yβŒͺ) (Ξ»y.f βŒ©x,yβŒͺ).
-
-(****************************** constructibility ******************************)
-definition constructible β‰ Ξ»s. CF s s.
-
-lemma constr_comp : βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
-  (βˆ€x. x β‰€ s2 x) β†’ constructible (s2 βˆ˜ s1).
-#s1 #s2 #Hs1 #Hs2 #Hle @(CF_comp β€¦ Hs1 Hs2) @O_plus @le_to_O #x [@Hle | //] 
-qed.
-
-lemma ext_constr: βˆ€s1,s2. (βˆ€x.s1 x = s2 x) β†’ 
-  constructible s1 β†’ constructible s2.
-#s1 #s2 #Hext #Hs1 @(ext_CF β€¦ Hext) @(monotonic_CF β€¦ Hs1)  #x >Hext //
-qed.
-
-lemma constr_prim_rec: βˆ€s1,s2. constructible s1 β†’ constructible s2 β†’
-  (βˆ€n,r,m. 2 * r β‰€ s2 βŒ©n,〈r,mβŒͺβŒͺ) β†’ constructible (unary_pr s1 s2).
-#s1 #s2 #Hs1 #Hs2 #Hincr @(CF_prim_rec β€¦ Hs1 Hs2) whd %{2} %{0} 
-#x #_ lapply (surj_pair x) * #a * #b #eqx >eqx whd in match (unary_pr ???); 
->fst_pair >snd_pair
-whd in match (unary_pr ???); >fst_pair >snd_pair elim a
-  [normalize //
-  |#n #Hind >prim_rec_S >fst_pair >snd_pair >fst_pair >snd_pair
-   >prim_rec_S @transitive_le [| @(monotonic_le_plus_l β€¦ Hind)]
-   @transitive_le [| @(monotonic_le_plus_l β€¦ (Hincr n ? b))] 
-   whd in match (unary_pr ???); >fst_pair >snd_pair //
-  ]
-qed.
-
-(********************************* simulation *********************************)
-
-axiom sU : nat β†’ nat. 
-
-axiom monotonic_sU: βˆ€i1,i2,x1,x2,s1,s2. i1 β‰€ i2 β†’ x1 β‰€ x2 β†’ s1 β‰€ s2 β†’
-  sU βŒ©i1,〈x1,s1βŒͺβŒͺ β‰€ sU βŒ©i2,〈x2,s2βŒͺβŒͺ.
-
-lemma monotonic_sU_aux : βˆ€x1,x2. fst x1 β‰€ fst x2 β†’ fst (snd x1) β‰€ fst (snd x2) β†’
-snd (snd x1) β‰€ snd (snd x2) β†’ sU x1 β‰€ sU x2.
-#x1 #x2 cases (surj_pair x1) #a1 * #y #eqx1 >eqx1 -eqx1 cases (surj_pair y) 
-#b1 * #c1 #eqy >eqy -eqy
-cases (surj_pair x2) #a2 * #y2 #eqx2 >eqx2 -eqx2 cases (surj_pair y2) 
-#b2 * #c2 #eqy2 >eqy2 -eqy2 >fst_pair >snd_pair >fst_pair >snd_pair 
->fst_pair >snd_pair >fst_pair >snd_pair @monotonic_sU
-qed.
-  
-axiom sU_le: βˆ€i,x,s. s β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_i: βˆ€i,x,s. MSC i β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-axiom sU_le_x: βˆ€i,x,s. MSC x β‰€ sU βŒ©i,〈x,sβŒͺβŒͺ.
-
-definition pU_unary β‰ Ξ»p. pU (fst p) (fst (snd p)) (snd (snd p)).
-
-axiom CF_U : CF sU pU_unary.
-
-definition termb_unary β‰ Ξ»x:β„•.termb (fst x) (fst (snd x)) (snd (snd x)).
-definition out_unary β‰ Ξ»x:β„•.out (fst x) (fst (snd x)) (snd (snd x)).
-
-lemma CF_termb: CF sU termb_unary. 
-@(ext_CF (fst βˆ˜ pU_unary)) [2: @CF_comp_fst @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >fst_pair % 
-qed.
-
-lemma CF_out: CF sU out_unary. 
-@(ext_CF (snd βˆ˜ pU_unary)) [2: @CF_comp_snd @CF_U]
-#n whd in βŠ’ (??%?); whd in  βŠ’ (??(?%)?); >snd_pair % 
-qed.
-
-
-(******************** complexity of g ********************)
-
-definition unary_g β‰ Ξ»h.Ξ»ux. g h (fst ux) (snd ux).
-definition auxg β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | eqb (min_input h i (snd ux)) (snd ux)} 
-    (out i (snd ux) (h (S i) (snd ux))).
-
-lemma compl_g1 : βˆ€h,s. CF s (auxg h) β†’ CF s (unary_g h).
-#h #s #H1 @(CF_compS ? (auxg h) H1) 
-qed.
-
-definition aux1g β‰ 
-  Ξ»h,ux. max_{i βˆˆ[fst ux,snd ux[ | (Ξ»p. eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) βŒ©i,uxβŒͺ} 
-    ((Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) βŒ©i,uxβŒͺ).
-
-lemma eq_aux : βˆ€h,x.aux1g h x = auxg h x.
-#h #x @same_bigop
-  [#n #_ >fst_pair >snd_pair // |#n #_ #_ >fst_pair >snd_pair //]
-qed.
-
-lemma compl_g2 : βˆ€h,s1,s2,s. 
-  CF s1
-    (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))) β†’
-  CF s2
-    (Ξ»p:β„•.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p)))) β†’
-  O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[fst x ,snd x[ }(s1 βŒ©i,xβŒͺ+s2 βŒ©i,xβŒͺ)) β†’ 
-  CF s (auxg h).
-#h #s1 #s2 #s #Hs1 #Hs2 #HO @(ext_CF (aux1g h)) 
-  [#n whd in βŠ’ (??%%); @eq_aux]
-@(CF_max β€¦ CF_fst CF_snd Hs1 Hs2 β€¦) @(O_trans β€¦ HO) 
-@O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-qed.  
-
-lemma compl_g3 : βˆ€h,s.
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))) β†’
-  CF s (Ξ»p:β„•.eqb (min_input h (fst p) (snd (snd p))) (snd (snd p))).
-#h #s #H @(CF_eqb β€¦ H) @(CF_comp β€¦ CF_snd CF_snd) @(O_trans β€¦ (proj1 β€¦ H))
-@O_plus // %{1} %{0} #n #_ >commutative_times <times_n_1 @monotonic_MSC //
-qed.
-
-definition min_input_aux β‰ Ξ»h,p.
-  ΞΌ_{y βˆˆ [S (fst p),snd (snd p)] } 
-    ((Ξ»x.termb (fst (snd x)) (fst x) (h (S (fst (snd x))) (fst x))) βŒ©y,pβŒͺ). 
-    
-lemma min_input_eq : βˆ€h,p. 
-    min_input_aux h p  =
-    min_input h (fst p) (snd (snd p)).
-#h #p >min_input_def whd in βŠ’ (??%?); >minus_S_S @min_f_g #i #_ #_ 
-whd in βŠ’ (??%%); >fst_pair >snd_pair //
-qed.
-
-definition termb_aux β‰ Ξ»h.
-  termb_unary βˆ˜ Ξ»p.〈fst (snd p),〈fst p,h (S (fst (snd p))) (fst p)βŒͺβŒͺ.
-
-lemma compl_g4 : βˆ€h,s1,s.
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-   (O s (Ξ»x.MSC x + βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ))) β†’
-  CF s (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #s #Hs1 #HO @(ext_CF (min_input_aux h))
- [#n whd in βŠ’ (??%%); @min_input_eq]
-@(CF_mu β€¦ MSC MSC β€¦ Hs1) 
-  [@CF_compS @CF_fst 
-  |@CF_comp_snd @CF_snd
-  |@(O_trans β€¦ HO) @O_plus [@O_plus @O_plus_l // | @O_plus_r //]
-qed.
-
-(************************* a couple of technical lemmas ***********************)
-lemma minus_to_0: βˆ€a,b. a β‰€ b β†’ minus a b = 0.
-#a elim a // #n #Hind * 
-  [#H @False_ind /2 by absurd/ | #b normalize #H @Hind @le_S_S_to_le /2/]
-qed.
-
-lemma sigma_bound:  βˆ€h,a,b. monotonic nat le h β†’ 
-  βˆ‘_{i βˆˆ [a,S b[ }(h i) β‰€  (S b-a)*h b.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut (b = pred (S b - a + a)) 
-    [<plus_minus_m_m // @le_S //] #Hb >Hb in match (h b);
-   generalize in match (S b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] @le_plus 
-      [@H @le_n |@(transitive_le β€¦ Hind) @le_times [//] @H //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (S b -a = 0) [@minus_to_0 //] #Hcut >Hcut //
-  ]
-qed.
-
-lemma sigma_bound_decr:  βˆ€h,a,b. (βˆ€a1,a2. a1 β‰€ a2 β†’ a2 < b β†’ h a2 β‰€ h a1) β†’ 
-  βˆ‘_{i βˆˆ [a,b[ }(h i) β‰€  (b-a)*h a.
-#h #a #b #H cases (decidable_le a b) 
-  [#leab cut ((b -a) +a β‰€ b) [/2 by le_minus_to_plus_r/] generalize in match (b -a);
-   #n elim n 
-    [//
-    |#m #Hind >bigop_Strue [2://] #Hm 
-     cut (m+a β‰€ b) [@(transitive_le β€¦ Hm) //] #Hm1
-     @le_plus [@H // |@(transitive_le β€¦ (Hind Hm1)) //]
-    ]
-  |#ltba lapply (not_le_to_lt β€¦ ltba) -ltba #ltba
-   cut (b -a = 0) [@minus_to_0 @lt_to_le @ltba] #Hcut >Hcut //
-  ]
-qed. 
-
-lemma coroll: βˆ€s1:natβ†’nat. (βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’ 
-O (Ξ»x.(snd (snd x)-fst x)*(s1 βŒ©snd (snd x),xβŒͺ)) 
-  (Ξ»x.βˆ‘_{i βˆˆ[S(fst x) ,S(snd (snd x))[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound β€¦)) [@Hs1|>minus_S_S //]
-qed.
-
-lemma coroll2: βˆ€s1:natβ†’nat. (βˆ€n,a,b. a β‰€ b β†’ b < snd n β†’ s1 βŒ©b,nβŒͺ β‰€ s1 βŒ©a,nβŒͺ) β†’ 
-O (Ξ»x.(snd x - fst x)*s1 βŒ©fst x,xβŒͺ) (Ξ»x.βˆ‘_{i βˆˆ[fst x,snd x[ }(s1 βŒ©i,xβŒͺ)).
-#s1 #Hs1 %{1} %{0} #n #_ >commutative_times <times_n_1 
-@(transitive_le β€¦ (sigma_bound_decr β€¦)) [2://] @Hs1 
-qed.
-
-(**************************** end of technical lemmas *************************)
-
-lemma compl_g5 : βˆ€h,s1.(βˆ€n. monotonic β„• le (Ξ»a:β„•.s1 βŒ©a,nβŒͺ)) β†’
-  (CF s1 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))) β†’
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*s1 βŒ©snd (snd x),xβŒͺ) 
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #s1 #Hmono #Hs1 @(compl_g4 β€¦ Hs1) @O_plus 
-[@O_plus_l // |@O_plus_r @coroll @Hmono]
-qed.
-
-lemma compl_g6: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst (snd x)) (snd (snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) 
-    (Ξ»p.termb (fst (snd p)) (fst p) (h (S (fst (snd p))) (fst p)))).
-#h #hconstr @(ext_CF (termb_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.MSC x + h (S (fst (snd x))) (fst x)) β€¦ CF_termb) 
-  [@CF_comp_pair
-    [@CF_comp_fst @(monotonic_CF β€¦ CF_snd) #x //
-    |@CF_comp_pair
-      [@(monotonic_CF β€¦ CF_fst) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst (snd x)),fst xβŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS @CF_comp_fst // |//]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus
-    [@O_plus
-      [@(O_trans β€¦ (Ξ»x.MSC (fst x) + MSC (max (fst (snd x)) (snd (snd x))))) 
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         >distributive_times_plus @le_plus [//]
-         cases (surj_pair b) #c * #d #eqb >eqb
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@O_plus [@le_to_O #x @sU_le_x |@le_to_O #x @sU_le_i]
-        ]     
-      |@le_to_O #n @sU_le
-      ] 
-    |@le_to_O #x @monotonic_sU // @(le_maxl β€¦ (le_n β€¦)) ]
-  ]
-qed.
-
-definition big : nat β†’nat β‰ Ξ»x. 
-  let m β‰ max (fst x) (snd x) in βŒ©m,mβŒͺ.
-
-lemma big_def : βˆ€a,b. big βŒ©a,bβŒͺ = βŒ©max a b,max a bβŒͺ.
-#a #b normalize >fst_pair >snd_pair // qed.
-
-lemma le_big : βˆ€x. x β‰€ big x. 
-#x cases (surj_pair x) #a * #b #eqx >eqx @le_pair >fst_pair >snd_pair 
-[@(le_maxl β€¦ (le_n β€¦)) | @(le_maxr β€¦ (le_n β€¦))]
-qed.
-
-definition faux2 β‰ Ξ»h.
-  (Ξ»x.MSC x + (snd (snd x)-fst x)*
-    (Ξ»x.sU βŒ©max (fst(snd x)) (snd(snd x)),〈fst x,h (S (fst (snd x))) (fst x)βŒͺβŒͺ) βŒ©snd (snd x),xβŒͺ).
-lemma compl_g7: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC x + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (faux2 h))
-  [#n normalize >fst_pair >snd_pair //]
-@compl_g5 [2:@(compl_g6 h hcostr)] #n #x #y #lexy >fst_pair >snd_pair 
->fst_pair >snd_pair @monotonic_sU // @hmono @lexy
-qed.
-
-lemma compl_g71: βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  CF (Ξ»x.MSC (big x) + (snd (snd x)-fst x)*sU βŒ©max (fst x) (snd x),〈snd (snd x),h (S (fst x)) (snd (snd x))βŒͺβŒͺ)
-    (Ξ»p:β„•.min_input h (fst p) (snd (snd p))).
-#h #hcostr #hmono @(monotonic_CF β€¦ (compl_g7 h hcostr hmono)) #x
-@le_plus [@monotonic_MSC //]
-cases (decidable_le (fst x) (snd(snd x))) 
-  [#Hle @le_times // @monotonic_sU  
-  |#Hlt >(minus_to_0 β€¦ (lt_to_le β€¦ )) [// | @not_le_to_lt @Hlt]
-  ]
-qed.
-
-definition out_aux β‰ Ξ»h.
-  out_unary βˆ˜ Ξ»p.〈fst p,〈snd(snd p),h (S (fst p)) (snd (snd p))βŒͺβŒͺ.
-
-lemma compl_g8: βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (CF (Ξ»x. sU βŒ©max (fst x) (snd x),〈snd(snd x),h (S (fst x)) (snd(snd x))βŒͺβŒͺ) 
-    (Ξ»p.out (fst p) (snd (snd p)) (h (S (fst p)) (snd (snd p))))).
-#h #hconstr @(ext_CF (out_aux h))
-  [#n normalize >fst_pair >snd_pair >fst_pair >snd_pair // ]
-@(CF_comp β€¦ (Ξ»x.h (S (fst x)) (snd(snd x)) + MSC x) β€¦ CF_out) 
-  [@CF_comp_pair
-    [@(monotonic_CF β€¦ CF_fst) #x //
-    |@CF_comp_pair
-      [@CF_comp_snd @(monotonic_CF β€¦ CF_snd) #x //
-      |@(ext_CF ((Ξ»x.h (fst x) (snd x))∘(Ξ»x.〈S (fst x),snd(snd x)βŒͺ)))
-        [#n normalize >fst_pair >snd_pair %]
-       @(CF_comp β€¦ MSC β€¦hconstr)
-        [@CF_comp_pair [@CF_compS // | @CF_comp_snd // ]
-        |@O_plus @le_to_O [//|#n >fst_pair >snd_pair //]
-        ]
-      ]
-    ]
-  |@O_plus 
-    [@O_plus 
-      [@le_to_O #n @sU_le 
-      |@(O_trans β€¦ (Ξ»x.MSC (max (fst x) (snd x))))
-        [%{2} %{0} #x #_ cases (surj_pair x) #a * #b #eqx >eqx
-         >fst_pair >snd_pair @(transitive_le β€¦ (MSC_pair β€¦)) 
-         whd in βŠ’ (??%); @le_plus 
-          [@monotonic_MSC @(le_maxl β€¦ (le_n β€¦)) 
-          |>commutative_times <times_n_1 @monotonic_MSC @(le_maxr β€¦ (le_n β€¦))  
-          ]
-        |@le_to_O #x @(transitive_le ???? (sU_le_i β€¦ )) //
-        ]
-      ]
-    |@le_to_O #x @monotonic_sU [@(le_maxl β€¦ (le_n β€¦))|//|//]
-  ]
-qed.
-
-lemma compl_g9 : βˆ€h. 
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (Ξ»x. (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + 
-      (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ)
-   (auxg h).
-#h #hconstr #hmono #hantimono 
-@(compl_g2 h ??? (compl_g3 β€¦ (compl_g71 h hconstr hmono)) (compl_g8 h hconstr))
-@O_plus 
-  [@O_plus_l @le_to_O #x >(times_n_1 (MSC x)) >commutative_times @le_times
-    [// | @monotonic_MSC // ]]
-@(O_trans β€¦ (coroll2 ??))
-  [#n #a #b #leab #ltb >fst_pair >fst_pair >snd_pair >snd_pair
-   cut (b β‰€ n) [@(transitive_le β€¦ (le_snd β€¦)) @lt_to_le //] #lebn
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [//|@(transitive_le β€¦ leab lebn)]] #maxa
-   cut (max b n = n) [normalize >le_to_leb_true //] #maxb
-   @le_plus
-    [@le_plus [>big_def >big_def >maxa >maxb //]
-     @le_times 
-      [/2 by monotonic_le_minus_r/ 
-      |@monotonic_sU // @hantimono [@le_S_S // |@ltb] 
-      ]
-    |@monotonic_sU // @hantimono [@le_S_S // |@ltb]
-    ] 
-  |@le_to_O #n >fst_pair >snd_pair
-   cut (max (fst n) n = n) [normalize >le_to_leb_true //] #Hmax >Hmax
-   >associative_plus >distributive_times_plus
-   @le_plus [@le_times [@le_S // |>big_def >Hmax //] |//] 
-  ]
-qed.
-
-definition sg β‰ Ξ»h,x.
-  (S (snd x-fst x))*MSC βŒ©x,xβŒͺ + (snd x-fst x)*(S(snd x-fst x))*sU βŒ©x,〈snd x,h (S (fst x)) (snd x)βŒͺβŒͺ.
-
-lemma sg_def : βˆ€h,a,b. 
-  sg h βŒ©a,bβŒͺ = (S (b-a))*MSC βŒ©βŒ©a,bβŒͺ,〈a,bβŒͺβŒͺ + 
-   (b-a)*(S(b-a))*sU βŒ©βŒ©a,bβŒͺ,〈b,h (S a) bβŒͺβŒͺ.
-#h #a #b whd in βŠ’ (??%?); >fst_pair >snd_pair // 
-qed. 
-
-lemma compl_g11 : βˆ€h.
-  constructible (Ξ»x. h (fst x) (snd x)) β†’
-  (βˆ€n. monotonic ? le (h n)) β†’ 
-  (βˆ€n,a,b. a β‰€ b β†’ b β‰€ n β†’ h b n β‰€ h a n) β†’
-  CF (sg h) (unary_g h).
-#h #hconstr #Hm #Ham @compl_g1 @(compl_g9 h hconstr Hm Ham)
-qed. 
-
-(**************************** closing the argument ****************************)
-
-let rec h_of_aux (r:nat β†’nat) (c,d,b:nat) on d : nat β‰ 
-  match d with 
-  [ O β‡’ c 
-  | S d1 β‡’ (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
-     d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (h_of_aux r c d1 b)βŒͺβŒͺ].
-
-lemma h_of_aux_O: βˆ€r,c,b.
-  h_of_aux r c O b  = c.
-// qed.
-
-lemma h_of_aux_S : βˆ€r,c,d,b. 
-  h_of_aux r c (S d) b = 
-    (S (S d))*(MSC βŒ©βŒ©b-(S d),bβŒͺ,〈b-(S d),bβŒͺβŒͺ) + 
-      (S d)*(S (S d))*sU βŒ©βŒ©b-(S d),bβŒͺ,〈b,r(h_of_aux r c d b)βŒͺβŒͺ.
-// qed.
-
-lemma h_of_aux_prim_rec : βˆ€r,c,n,b. h_of_aux r c n b =
-  prim_rec (Ξ»x.c) 
-   (Ξ»x.let d β‰ S(fst x) in 
-       let b β‰ snd (snd x) in
-       (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
-        d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (fst (snd x))βŒͺβŒͺ) n b.
-#r #c #n #b elim n
-  [>h_of_aux_O normalize //
-  |#n1 #Hind >h_of_aux_S >prim_rec_S >snd_pair >snd_pair >fst_pair 
-   >fst_pair <Hind //
-  ]
-qed.
-
-lemma h_of_aux_constr : 
-βˆ€r,c. constructible (Ξ»x.h_of_aux r c (fst x) (snd x)).
-#r #c 
-  @(ext_constr β€¦ 
-    (unary_pr (Ξ»x.c) 
-     (Ξ»x.let d β‰ S(fst x) in 
-       let b β‰ snd (snd x) in
-       (S d)*(MSC βŒ©βŒ©b-d,bβŒͺ,〈b-d,bβŒͺβŒͺ) +
-        d*(S d)*sU βŒ©βŒ©b-d,bβŒͺ,〈b,r (fst (snd x))βŒͺβŒͺ)))
-  [#n @sym_eq whd in match (unary_pr ???); @h_of_aux_prim_rec
-  |@constr_prim_rec
-
-definition h_of β‰ Ξ»r,p. 
-  let m β‰ max (fst p) (snd p) in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (snd p - fst p) (snd p).
-
-lemma h_of_O: βˆ€r,a,b. b β‰€ a β†’ 
-  h_of r βŒ©a,bβŒͺ = let m β‰ max a b in MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ.
-#r #a #b #Hle normalize >fst_pair >snd_pair >(minus_to_0 β€¦ Hle) //
-qed.
-
-lemma h_of_def: βˆ€r,a,b.h_of r βŒ©a,bβŒͺ = 
-  let m β‰ max a b in 
-  h_of_aux r (MSC βŒ©βŒ©m,mβŒͺ,〈m,mβŒͺβŒͺ) (b - a) b.
-#r #a #b normalize >fst_pair >snd_pair //
-qed.
-  
-lemma mono_h_of_aux: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€d,d1,c,c1,b,b1.c β‰€ c1 β†’ d β‰€ d1 β†’ b β‰€ b1 β†’ 
-  h_of_aux r c d b β‰€ h_of_aux r c1 d1 b1.
-#r #Hr #monor #d #d1 lapply d -d elim d1 
-  [#d #c #c1 #b #b1 #Hc #Hd @(le_n_O_elim ? Hd) #leb 
-   >h_of_aux_O >h_of_aux_O  //
-  |#m #Hind #d #c #c1 #b #b1 #lec #led #leb cases (le_to_or_lt_eq β€¦ led)
-    [#ltd @(transitive_le β€¦ (Hind β€¦ lec ? leb)) [@le_S_S_to_le @ltd]
-     >h_of_aux_S @(transitive_le ???? (le_plus_n β€¦))
-     >(times_n_1 (h_of_aux r c1 m b1)) in βŠ’ (?%?); 
-     >commutative_times @le_times [//|@(transitive_le β€¦ (Hr ?)) @sU_le]
-    |#Hd >Hd >h_of_aux_S >h_of_aux_S 
-     cut (b-S m β‰€ b1 - S m) [/2 by monotonic_le_minus_l/] #Hb1
-     @le_plus [@le_times //] 
-      [@monotonic_MSC @le_pair @le_pair //
-      |@le_times [//] @monotonic_sU 
-        [@le_pair // |// |@monor @Hind //]
-      ]
-    ]
-  ]
-qed.
-
-lemma mono_h_of2: βˆ€r.(βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’
-  βˆ€i,b,b1. b β‰€ b1 β†’ h_of r βŒ©i,bβŒͺ β‰€ h_of r βŒ©i,b1βŒͺ.
-#r #Hr #Hmono #i #a #b #leab >h_of_def >h_of_def
-cut (max i a β‰€ max i b)
-  [@to_max 
-    [@(le_maxl β€¦ (le_n β€¦))|@(transitive_le β€¦ leab) @(le_maxr β€¦ (le_n β€¦))]]
-#Hmax @(mono_h_of_aux r Hr Hmono) 
-  [@monotonic_MSC @le_pair @le_pair @Hmax |/2 by monotonic_le_minus_l/ |@leab]
-qed.
-
-axiom h_of_constr : βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  constructible (h_of r).
-
-lemma speed_compl: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  CF (h_of r) (unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ))).
-#r #Hr #Hmono #Hconstr @(monotonic_CF β€¦ (compl_g11 β€¦)) 
-  [#x cases (surj_pair x) #a * #b #eqx >eqx 
-   >sg_def cases (decidable_le b a)
-    [#leba >(minus_to_0 β€¦ leba) normalize in βŠ’ (?%?);
-     <plus_n_O <plus_n_O >h_of_def 
-     cut (max a b = a) 
-      [normalize cases (le_to_or_lt_eq β€¦ leba)
-        [#ltba >(lt_to_leb_false β€¦ ltba) % 
-        |#eqba <eqba >(le_to_leb_true β€¦ (le_n ?)) % ]]
-     #Hmax >Hmax normalize >(minus_to_0 β€¦ leba) normalize
-     @monotonic_MSC @le_pair @le_pair //
-    |#ltab >h_of_def >h_of_def
-     cut (max a b = b) 
-      [normalize >(le_to_leb_true β€¦ ) [%] @lt_to_le @not_le_to_lt @ltab]
-     #Hmax >Hmax 
-     cut (max (S a) b = b) 
-      [whd in βŠ’ (??%?);  >(le_to_leb_true β€¦ ) [%] @not_le_to_lt @ltab]
-     #Hmax1 >Hmax1
-     cut (βˆƒd.b - a = S d) 
-       [%{(pred(b-a))} >S_pred [//] @lt_plus_to_minus_r @not_le_to_lt @ltab] 
-     * #d #eqd >eqd  
-     cut (b-S a = d) [//] #eqd1 >eqd1 >h_of_aux_S >eqd1 
-     cut (b - S d = a) 
-       [@plus_to_minus >commutative_plus @minus_to_plus 
-         [@lt_to_le @not_le_to_lt // | //]] #eqd2 >eqd2
-     normalize //
-    ]
-  |#n #a #b #leab #lebn >h_of_def >h_of_def
-   cut (max a n = n) 
-    [normalize >le_to_leb_true [%|@(transitive_le β€¦ leab lebn)]] #Hmaxa
-   cut (max b n = n) 
-    [normalize >(le_to_leb_true β€¦ lebn) %] #Hmaxb 
-   >Hmaxa >Hmaxb @Hmono @(mono_h_of_aux r β€¦ Hr Hmono) // /2 by monotonic_le_minus_r/
-  |#n #a #b #leab @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ leab)
-  |@(constr_comp β€¦ Hconstr Hr) @(ext_constr (h_of r))
-    [#x cases (surj_pair x) #a * #b #eqx >eqx >fst_pair >snd_pair //]  
-   @(h_of_constr r Hr Hmono Hconstr)
-  ]
-qed.
-
-lemma speed_compl_i: βˆ€r:nat β†’nat. 
-  (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆ€i. CF (Ξ»x.h_of r βŒ©i,xβŒͺ) (Ξ»x.g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) i x).
-#r #Hr #Hmono #Hconstr #i 
-@(ext_CF (Ξ»x.unary_g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) βŒ©i,xβŒͺ))
-  [#n whd in βŠ’ (??%%); @eq_f @sym_eq >fst_pair >snd_pair %]
-@smn @(ext_CF β€¦ (speed_compl r Hr Hmono Hconstr)) #n //
-qed.
-
-(**************************** the speedup theorem *****************************)
-theorem pseudo_speedup: 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ O sf (r βˆ˜ sg).
-(* βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. *)
-#r #Hr #Hmono #Hconstr
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha %{m} %{(max (S i) a)} #n #ltin @lt_to_le @not_le_to_lt 
-  @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf %{n} % 
-  [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf) //
- ]
-qed.
-
-theorem pseudo_speedup': 
-  βˆ€r:nat β†’nat. (βˆ€x. x β‰€ r x) β†’ monotonic ? le r β†’ constructible r β†’
-  βˆƒf.βˆ€sf. CF sf f β†’ βˆƒg,sg. f β‰ˆ g βˆ§ CF sg g βˆ§ 
-  (* Β¬ O (r βˆ˜ sg) sf. *)
-  βˆƒm,a.βˆ€n. a≀n β†’ r(sg a) < m * sf n. 
-#r #Hr #Hmono #Hconstr 
-(* f is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0) *) 
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) 0)} #sf * #H * #i *
-#Hcodei #HCi 
-(* g is (g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i)) *)
-%{(g (Ξ»i,x. r(h_of r βŒ©i,xβŒͺ)) (S i))}
-(* sg is (Ξ»x.h_of r βŒ©i,xβŒͺ) *)
-%{(Ξ»x. h_of r βŒ©S i,xβŒͺ)}
-lapply (speed_compl_i β€¦ Hr Hmono Hconstr (S i)) #Hg
-%[%[@condition_1 |@Hg]
- |cases Hg #H1 * #j * #Hcodej #HCj
-  lapply (condition_2 β€¦ Hcodei) #Hcond2 (* @not_to_not *)
-  cases HCi #m * #a #Ha
-  %{m} %{(max (S i) a)} #n #ltin @not_le_to_lt @(not_to_not β€¦ Hcond2) -Hcond2 #Hlesf 
-  %{n} % [@(transitive_le β€¦ ltin) @(le_maxl β€¦ (le_n β€¦))]
-  cases (Ha n ?) [2: @(transitive_le β€¦ ltin) @(le_maxr β€¦ (le_n β€¦))] 
-  #y #Uy %{y} @(monotonic_U β€¦ Uy) @(transitive_le β€¦ Hlesf)
-  @Hmono @(mono_h_of2 β€¦ Hr Hmono β€¦ ltin)
- ]
-qed.
-  
diff --git a/matita/matita/lib/turing/multi_to_mono/multi_to_mono.ma b/matita/matita/lib/turing/multi_to_mono/multi_to_mono.ma
deleted file mode 100644 (file)
index 0e9bce5..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-include "turing/auxiliary_machines1.ma".
-include "turing/multi_to_mono/shift_trace_machines.ma".
-
-(******************************************************************************)
-(* mtiL: complete move L for tape i. We reaching the left border of trace i,  *)
-(* add a blank if there is no more tape, then move the i-trace and finally    *)
-(* come back to the head position.                                            *)
-(******************************************************************************)
-
-(* we say that a tape is regular if for any trace after the first blank we
-  only have other blanks *)
-  
-definition all_blanks_in β‰ Ξ»sig,l.
-  βˆ€x. mem ? x l β†’ x = blank sig.  
-definition regular_i  β‰ Ξ»sig,n.Ξ»l:list (multi_sig sig n).Ξ»i.
-  all_blanks_in ? (after_blank ? (trace sig n i l)).
-
-definition regular_trace β‰ Ξ»sig,n,a.Ξ»ls,rs:list (multi_sig sig n).Ξ»i.
-  Or (And (regular_i sig n (a::ls) i) (regular_i sig n rs i))
-     (And (regular_i sig n ls i) (regular_i sig n (a::rs) i)).
-         
-axiom regular_tail: βˆ€sig,n,l,i.
-  regular_i sig n l i β†’ regular_i sig n (tail ? l) i.
-  
-axiom regular_extend: βˆ€sig,n,l,i.
-   regular_i sig n l i β†’ regular_i sig n (l@[all_blank sig n]) i.
-
-axiom all_blank_after_blank: βˆ€sig,n,l1,b,l2,i. 
-  nth i ? (vec β€¦ b) (blank ?) = blank ? β†’ 
-  regular_i sig n (l1@b::l2) i β†’ all_blanks_in ? (trace sig n i l2).
-   
-lemma regular_trace_extl:  βˆ€sig,n,a,ls,rs,i.
-  regular_trace sig n a ls rs i β†’ 
-    regular_trace sig n a (ls@[all_blank sig n]) rs i.
-#sig #n #a #ls #rs #i *
-  [* #H1 #H2 % % // @(regular_extend β€¦ H1)
-  |* #H1 #H2 %2 % // @(regular_extend β€¦ H1)
-  ]
-qed.
-
-lemma regular_cons_hd_rs: βˆ€sig,n.βˆ€a:multi_sig sig n.βˆ€ls,rs1,rs2,i.
-  regular_trace sig n a ls (rs1@rs2) i β†’ 
-    regular_trace sig n a ls (rs1@((hd ? rs2 (all_blank β€¦))::(tail ? rs2))) i.
-#sig #n #a #ls #rs1 #rs2 #i cases rs2 [2: #b #tl #H @H] 
-*[* #H1 >append_nil #H2 %1 % 
-   [@H1 | whd in match (hd ???); @(regular_extend β€¦ rs1) //]
- |* #H1 >append_nil #H2 %2 % 
-   [@H1 | whd in match (hd ???); @(regular_extend β€¦ (a::rs1)) //]
- ]
-qed.
-
-lemma eq_trace_to_regular : βˆ€sig,n.βˆ€a1,a2:multi_sig sig n.βˆ€ls1,ls2,rs1,rs2,i.
-   nth i ? (vec β€¦ a1) (blank ?) = nth i ? (vec β€¦ a2) (blank ?) β†’
-   trace sig n i ls1 = trace sig n i ls2 β†’ 
-   trace sig n i rs1 = trace sig n i rs2 β†’
-   regular_trace sig n a1 ls1 rs1 i β†’ 
-     regular_trace sig n a2 ls2 rs2 i.
-#sig #n #a1 #a2 #ls1 #ls2 #rs1 #rs2 #i #H1 #H2 #H3 #H4
-whd in match (regular_trace ??????); whd in match (regular_i ????);
-whd in match (regular_i ?? rs2 ?); whd in match (regular_i ?? ls2 ?);
-whd in match (regular_i ?? (a2::rs2) ?); whd in match (trace ????);
-<trace_def whd in match (trace ??? (a2::rs2)); <trace_def 
-<H1 <H2 <H3 @H4
-qed.
-
-(******************************* move_to_blank_L ******************************)
-(* we compose machines together to reduce the number of output cases, and 
-   improve semantics *)
-   
-definition move_to_blank_L β‰ Ξ»sig,n,i.
-  (move_until ? L (no_blank sig n i)) Β· extend ? (all_blank sig n).
-
-(*
-definition R_move_to_blank_L β‰ Ξ»sig,n,i,t1,t2.
-(current ? t1 = None ? β†’ 
-  t2 = midtape (multi_sig sig n) (left ? t1) (all_blank β€¦) (right ? t1)) βˆ§
-βˆ€ls,a,rs.t1 = midtape ? ls a rs β†’ 
-  ((no_blank sig n i a = false) βˆ§ t2 = t1) βˆ¨
-  (βˆƒb,ls1,ls2.
-    (no_blank sig n i b = false) βˆ§ 
-    (βˆ€j.j β‰€n β†’ to_blank_i ?? j (ls1@b::ls2) = to_blank_i ?? j ls) βˆ§
-    t2 = midtape ? ls2 b ((reverse ? (a::ls1))@rs)). 
-*)
-
-definition R_move_to_blank_L β‰ Ξ»sig,n,i,t1,t2.
-(current ? t1 = None ? β†’ 
-  t2 = midtape (multi_sig sig n) (left ? t1) (all_blank β€¦) (right ? t1)) βˆ§
-βˆ€ls,a,rs.
-  t1 = midtape (multi_sig sig n) ls a rs β†’ 
-  regular_i sig n (a::ls) i β†’
-  (βˆ€j. j β‰  i β†’ regular_trace β€¦ a ls rs j) β†’
-  (βˆƒb,ls1,ls2.
-    (regular_i sig n (ls1@b::ls2) i) βˆ§ 
-    (βˆ€j. j β‰  i β†’ regular_trace β€¦ 
-      (hd ? (ls1@b::ls2) (all_blank β€¦)) (tail ? (ls1@b::ls2)) rs j) βˆ§ 
-    (no_blank sig n i b = false) βˆ§ 
-    (hd (multi_sig sig n) (ls1@[b]) (all_blank β€¦) = a) βˆ§ (* not implied by the next fact *)
-    (βˆ€j.j β‰€n β†’ to_blank_i ?? j (ls1@b::ls2) = to_blank_i ?? j (a::ls)) βˆ§
-    t2 = midtape ? ls2 b ((reverse ? ls1)@rs)).
-
-theorem sem_move_to_blank_L: βˆ€sig,n,i. 
-  move_to_blank_L sig n i  βŠ¨ R_move_to_blank_L sig n i.
-#sig #n #i 
-@(sem_seq_app ?????? 
-  (ssem_move_until_L ? (no_blank sig n i)) (sem_extend ? (all_blank sig n)))
-#tin #tout * #t1 * * #Ht1a #Ht1b * #Ht2a #Ht2b %
-  [#Hcur >(Ht1a Hcur) in Ht2a; /2 by /
-  |#ls #a #rs #Htin #Hreg #Hreg2 -Ht1a cases (Ht1b β€¦ Htin)
-    [* #Hnb #Ht1 -Ht1b -Ht2a >Ht1 in Ht2b; >Htin #H 
-     %{a} %{[ ]} %{ls} 
-     %[%[%[%[%[@Hreg|@Hreg2]|@Hnb]|//]|//]|@H normalize % #H1 destruct (H1)]
-    |* 
-    [(* we find the blank *)
-     * #ls1 * #b * #ls2 * * * #H1 #H2 #H3 #Ht1
-     >Ht1 in Ht2b; #Hout -Ht1b
-     %{b} %{(a::ls1)} %{ls2} 
-     %[%[%[%[%[>H1 in Hreg; #H @H 
-              |#j #jneqi whd in match (hd ???); whd in match (tail ??);
-               <H1 @(Hreg2 j jneqi)]|@H2] |//]|>H1 //]
-      |@Hout normalize % normalize #H destruct (H)
-      ]
-    |* #b * #lss * * #H1 #H2 #Ht1 -Ht1b >Ht1 in Ht2a; 
-     whd in match (left ??); whd in match (right ??); #Hout
-     %{(all_blank β€¦)} %{(lss@[b])} %{[]}
-     %[%[%[%[%[<H2 @regular_extend // 
-              |<H2 #j #jneqi whd in match (hd ???); whd in match (tail ??); 
-               @regular_trace_extl @Hreg2 //]
-            |whd in match (no_blank ????); >blank_all_blank //]
-          |<H2 //]
-        |#j #lejn <H2 @sym_eq @to_blank_i_ext]
-      |>reverse_append >reverse_single @Hout normalize // 
-      ]
-    ]
-  ]
-qed.
-
-(******************************************************************************)
-   
-definition shift_i_L β‰ Ξ»sig,n,i.
-   ncombf_r (multi_sig β€¦) (shift_i sig n i) (all_blank sig n) Β·
-   mti sig n i Β· 
-   extend ? (all_blank sig n).
-   
-definition R_shift_i_L β‰ Ξ»sig,n,i,t1,t2.
-    (βˆ€a,ls,rs. 
-      t1 = midtape ? ls a rs  β†’ 
-      ((βˆƒrs1,b,rs2,a1,rss.
-        rs = rs1@b::rs2 βˆ§ 
-        nth i ? (vec β€¦ b) (blank ?) = (blank ?) βˆ§
-        (βˆ€x. mem ? x rs1 β†’ nth i ? (vec β€¦ x) (blank ?) β‰  (blank ?)) βˆ§
-        shift_l sig n i (a::rs1) (a1::rss) βˆ§
-        t2 = midtape (multi_sig sig n) ((reverse ? (a1::rss))@ls) b rs2) βˆ¨
-      (βˆƒb,rss. 
-        (βˆ€x. mem ? x rs β†’ nth i ? (vec β€¦ x) (blank ?) β‰  (blank ?)) βˆ§
-        shift_l sig n i (a::rs) (rss@[b]) βˆ§
-        t2 = midtape (multi_sig sig n) 
-          ((reverse ? (rss@[b]))@ls) (all_blank sig n) [ ]))).
-
-definition R_shift_i_L_new β‰ Ξ»sig,n,i,t1,t2.
-  (βˆ€a,ls,rs. 
-   t1 = midtape ? ls a rs  β†’ 
-   βˆƒrs1,b,rs2,rss.
-      b = hd ? rs2 (all_blank sig n) βˆ§
-      nth i ? (vec β€¦ b) (blank ?) = (blank ?) βˆ§
-      rs = rs1@rs2 βˆ§ 
-      (βˆ€x. mem ? x rs1 β†’ nth i ? (vec β€¦ x) (blank ?) β‰  (blank ?)) βˆ§
-      shift_l sig n i (a::rs1) rss βˆ§
-      t2 = midtape (multi_sig sig n) ((reverse ? rss)@ls) b (tail ? rs2)). 
-          
-theorem sem_shift_i_L: βˆ€sig,n,i. shift_i_L sig n i  βŠ¨ R_shift_i_L sig n i.
-#sig #n #i 
-@(sem_seq_app ?????? 
-  (sem_ncombf_r (multi_sig sig n) (shift_i sig n i)(all_blank sig n))
-   (sem_seq ????? (ssem_mti sig n i) 
-    (sem_extend ? (all_blank sig n))))
-#tin #tout * #t1 * * #Ht1a #Ht1b * #t2 * * #Ht2a #Ht2b * #Htout1 #Htout2
-#a #ls #rs cases rs
-  [#Htin %2 %{(shift_i sig n i a (all_blank sig n))} %{[ ]} 
-   %[%[#x @False_ind | @daemon]
-    |lapply (Ht1a β€¦ Htin) -Ht1a -Ht1b #Ht1 
-     lapply (Ht2a β€¦ Ht1) -Ht2a -Ht2b #Ht2 >Ht2 in Htout1; 
-     >Ht1 whd in match (left ??); whd in match (right ??); #Htout @Htout // 
-    ]
-  |#a1 #rs1 #Htin 
-   lapply (Ht1b β€¦ Htin) -Ht1a -Ht1b #Ht1 
-   lapply (Ht2b β€¦ Ht1) -Ht2a -Ht2b *
-    [(* a1 is blank *) * #H1 #H2 %1
-     %{[ ]} %{a1} %{rs1} %{(shift_i sig n i a a1)} %{[ ]}
-     %[%[%[%[// |//] |#x @False_ind] | @daemon]
-      |>Htout2 [>H2 >reverse_single @Ht1 |>H2 >Ht1 normalize % #H destruct (H)]
-      ]
-    |*
-    [* #rs10 * #b * #rs2 * #rss * * * * #H1 #H2 #H3 #H4
-     #Ht2 %1 
-     %{(a1::rs10)} %{b} %{rs2} %{(shift_i sig n i a a1)} %{rss}
-     %[%[%[%[>H1 //|//] |@H3] |@daemon ]
-      |>reverse_cons >associative_append 
-       >H2 in Htout2; #Htout >Htout [@Ht2| >Ht2 normalize % #H destruct (H)]  
-      ]
-    |* #b * #rss * * #H1 #H2 
-     #Ht2 %2
-     %{(shift_i sig n i b (all_blank sig n))} %{(shift_i sig n i a a1::rss)}
-     %[%[@H1 |@daemon ]
-      |>Ht2 in Htout1; #Htout >Htout //
-       whd in match (left ??); whd in match (right ??);
-       >reverse_append >reverse_single >associative_append  >reverse_cons
-       >associative_append // 
-       ]
-     ]
-   ]
- ]
-qed.
-theorem sem_shift_i_L_new: βˆ€sig,n,i. 
-  shift_i_L sig n i  βŠ¨ R_shift_i_L_new sig n i.
-#sig #n #i 
-@(Realize_to_Realize β€¦ (sem_shift_i_L sig n i))
-#t1 #t2 #H #a #ls #rs #Ht1 lapply (H a ls rs Ht1) *
-  [* #rs1 * #b * #rs2 * #a1 * #rss * * * * #H1 #H2 #H3 #H4 #Ht2
-   %{rs1} %{b} %{(b::rs2)} %{(a1::rss)} 
-   %[%[%[%[%[//|@H2]|@H1]|@H3]|@H4] | whd in match (tail ??); @Ht2]
-  |* #b * #rss * * #H1 #H2 #Ht2
-   %{rs} %{(all_blank sig n)} %{[]} %{(rss@[b])} 
-   %[%[%[%[%[//|@blank_all_blank]|//]|@H1]|@H2] | whd in match (tail ??); @Ht2]
-  ]
-qed.
-   
-
-(*******************************************************************************
-The following machine implements a full move of for a trace: we reach the left 
-border, shift the i-th trace and come back to the head position. *)  
-
-(* this exclude the possibility that traces do not overlap: the head must 
-remain inside all traces *)
-
-definition mtiL β‰ Ξ»sig,n,i.
-   move_to_blank_L sig n i Β· 
-   shift_i_L sig n i Β·
-   move_until ? L (no_head sig n). 
-   
-definition Rmtil β‰ Ξ»sig,n,i,t1,t2.
-  βˆ€ls,a,rs. 
-   t1 = midtape (multi_sig sig n) ls a rs β†’ 
-   nth n ? (vec β€¦ a) (blank ?) = head ? β†’  
-   (βˆ€i.regular_trace sig n a ls rs i) β†’ 
-   (* next: we cannot be on rightof on trace i *)
-   (nth i ? (vec β€¦ a) (blank ?) = (blank ?) 
-     β†’ nth i ? (vec β€¦ (hd ? rs (all_blank β€¦))) (blank ?) β‰  (blank ?)) β†’
-   no_head_in β€¦ ls β†’   
-   no_head_in β€¦ rs  β†’ 
-   (βˆƒls1,a1,rs1.
-     t2 = midtape (multi_sig β€¦) ls1 a1 rs1 βˆ§
-     (βˆ€i.regular_trace β€¦ a1 ls1 rs1 i) βˆ§
-     (βˆ€j. j β‰€ n β†’ j β‰  i β†’ to_blank_i ? n j (a1::ls1) = to_blank_i ? n j (a::ls)) βˆ§
-     (βˆ€j. j β‰€ n β†’ j β‰  i β†’ to_blank_i ? n j rs1 = to_blank_i ? n j rs) βˆ§
-     (to_blank_i ? n i ls1 = to_blank_i ? n i (a::ls)) βˆ§
-     (to_blank_i ? n i (a1::rs1)) = to_blank_i ? n i rs).
-
-theorem sem_Rmtil: βˆ€sig,n,i. i < n β†’ mtiL sig n i  βŠ¨ Rmtil sig n i.
-#sig #n #i #lt_in
-@(sem_seq_app ?????? 
-  (sem_move_to_blank_L β€¦ )
-   (sem_seq ????? (sem_shift_i_L_new β€¦)
-    (ssem_move_until_L ? (no_head sig n))))
-#tin #tout * #t1 * * #_ #Ht1 * #t2 * #Ht2 * #_ #Htout
-(* we start looking into Rmitl *)
-#ls #a #rs #Htin (* tin is a midtape *)
-#Hhead #Hreg #no_rightof #Hnohead_ls #Hnohead_rs 
-cut (regular_i sig n (a::ls) i)
-  [cases (Hreg i) * // 
-   cases (true_or_false (nth i ? (vec β€¦ a) (blank ?) == (blank ?))) #Htest
-    [#_ @daemon (* absurd, since hd rs non e' blank *)
-    |#H #_ @daemon]] #Hreg1
-lapply (Ht1 β€¦ Htin Hreg1 ?) [#j #_ @Hreg] -Ht1 -Htin
-* #b * #ls1 * #ls2 * * * * * #reg_ls1_i #reg_ls1_j #Hno_blankb #Hhead #Hls1 #Ht1
-lapply (Ht2 β€¦ Ht1) -Ht2 -Ht1 
-* #rs1 * #b0 * #rs2 * #rss * * * * * #Hb0 #Hb0blank #Hrs1 #Hrs1b #Hrss #Ht2
-(* we need to recover the position of the head of the emulated machine
-   that is the head of ls1. This is somewhere inside rs1 *) 
-cut (βˆƒrs11. rs1 = (reverse ? ls1)@rs11)
-  [cut (ls1 = [ ] βˆ¨ βˆƒaa,tlls1. ls1 = aa::tlls1)
-    [cases ls1 [%1 // | #aa #tlls1 %2 %{aa} %{tlls1} //]] *
-      [#H1ls1 %{rs1} >H1ls1 //
-      |* #aa * #tlls1 #H1ls1 >H1ls1 in Hrs1; 
-       cut (aa = a) [>H1ls1 in Hls1; #H @(to_blank_hd β€¦ H)] #eqaa >eqaa  
-       #Hrs1_aux cases (compare_append β€¦ (sym_eq β€¦ Hrs1_aux)) #l *
-        [* #H1 #H2 %{l} @H1
-        |(* this is absurd : if l is empty, the case is as before.
-           if l is not empty then it must start with a blank, since it is the
-           first character in rs2. But in this case we would have a blank 
-           inside ls1=a::tls1 that is absurd *)
-          @daemon
-        ]]]   
-   * #rs11 #H1
-cut (rs = rs11@rs2)
-  [@(injective_append_l β€¦ (reverse β€¦ ls1)) >Hrs1 <associative_append <H1 //] #H2
-lapply (Htout β€¦ Ht2) -Htout -Ht2 *
-  [(* the current character on trace i holds the head-mark.
-      The case is absurd, since b0 is the head of rs2, that is a sublist of rs, 
-      and the head-mark is not in rs *)
-   * #H3 @False_ind @(absurd (nth n ? (vec β€¦ b0) (blank sig) = head ?)) 
-     [@(\P ?) @injective_notb @H3 ]
-   @Hnohead_rs >H2 >trace_append @mem_append_l2 
-   lapply Hb0 cases rs2 
-    [whd in match (hd ???); #H >H in H3; whd in match (no_head ???); 
-     >all_blank_n normalize -H #H destruct (H); @False_ind
-    |#c #r #H4 %1 >H4 //
-    ]
-  |* 
-  [(* we reach the head position *)
-   (* cut (trace sig n j (a1::ls20)=trace sig n j (ls1@b::ls2)) *)
-   * #ls10 * #a1 * #ls20 * * * #Hls20 #Ha1 #Hnh #Htout
-   cut (βˆ€j.j β‰  i β†’
-      trace sig n j (reverse (multi_sig sig n) rs1@b::ls2) = 
-      trace sig n j (ls10@a1::ls20))
-    [#j #ineqj >append_cons <reverse_cons >trace_def <map_append <reverse_map
-     lapply (trace_shift_neq β€¦lt_in ? (sym_not_eq β€¦ ineqj) β€¦ Hrss) [//] #Htr
-     <(trace_def β€¦  (b::rs1)) <Htr >reverse_map >map_append @eq_f @Hls20 ] 
-   #Htracej
-   cut (trace sig n i (reverse (multi_sig sig n) (rs1@[b0])@ls2) = 
-        trace sig n i (ls10@a1::ls20))
-    [>trace_def <map_append <reverse_map <map_append <(trace_def β€¦ [b0]) 
-     cut (trace sig n i [b0] = [blank ?]) [@daemon] #Hcut >Hcut
-     lapply (trace_shift β€¦ lt_in β€¦ Hrss) [//] whd in match (tail ??); #Htr <Htr
-     >reverse_map >map_append <trace_def <Hls20 % 
-    ] 
-   #Htracei
-   cut (βˆ€j. j β‰  i β†’
-      (trace sig n j (reverse (multi_sig sig n) rs11) = trace sig n j ls10) βˆ§ 
-      (trace sig n j (ls1@b::ls2) = trace sig n j (a1::ls20)))
-   [@daemon (* si fa 
-     #j #ineqj @(first_P_to_eq ? (Ξ»x. x β‰  head ?))
-      [lapply (Htracej β€¦ ineqj) >trace_def in βŠ’ (%β†’?); <map_append 
-       >trace_def in βŠ’ (%β†’?); <map_append #H @H  
-      | *) ] #H2
-  cut ((trace sig n i (b0::reverse ? rs11) = trace sig n i (ls10@[a1])) βˆ§ 
-      (trace sig n i (ls1@ls2) = trace sig n i ls20))
-   [>H1 in Htracei; >reverse_append >reverse_single >reverse_append 
-     >reverse_reverse >associative_append >associative_append
-     @daemon
-    ] #H3    
-  cut (βˆ€j. j β‰  i β†’ 
-    trace sig n j (reverse (multi_sig sig n) ls10@rs2) = trace sig n j rs)
-    [#j #jneqi @(injective_append_l β€¦ (trace sig n j (reverse ? ls1)))
-     >map_append >map_append >Hrs1 >H1 >associative_append 
-     <map_append <map_append in βŠ’ (???%); @eq_f 
-     <map_append <map_append @eq_f2 // @sym_eq 
-     <(reverse_reverse β€¦ rs11) <reverse_map <reverse_map in βŠ’ (???%);
-     @eq_f @(proj1 β€¦ (H2 j jneqi))] #Hrs_j
-   %{ls20} %{a1} %{(reverse ? (b0::ls10)@tail (multi_sig sig n) rs2)}
-   %[%[%[%[%[@Htout
-    |#j cases (decidable_eq_nat j i)
-      [#eqji >eqji (* by cases wether a1 is blank *)
-       @daemon
-      |#jneqi lapply (reg_ls1_j β€¦ jneqi) #H4 
-       >reverse_cons >associative_append >Hb0 @regular_cons_hd_rs
-       @(eq_trace_to_regular β€¦ H4)
-        [<hd_trace >(proj2 β€¦ (H2 β€¦ jneqi)) >hd_trace %
-        |<tail_trace >(proj2 β€¦ (H2 β€¦ jneqi)) >tail_trace %
-        |@sym_eq @Hrs_j //
-        ]
-      ]]
-    |#j #lejn #jneqi <(Hls1 β€¦ lejn) 
-     >to_blank_i_def >to_blank_i_def @eq_f @sym_eq @(proj2 β€¦ (H2 j jneqi))]
-    |#j #lejn #jneqi >reverse_cons >associative_append >Hb0
-     <to_blank_hd_cons >to_blank_i_def >to_blank_i_def @eq_f @Hrs_j //]
-    |<(Hls1 i) [2:@lt_to_le //] 
-     lapply (all_blank_after_blank β€¦ reg_ls1_i) 
-       [@(\P ?) @daemon] #allb_ls2
-     whd in match (to_blank_i ????); <(proj2 β€¦ H3)
-     @daemon ]
-    |>reverse_cons >associative_append  
-     cut (to_blank_i sig n i rs = to_blank_i sig n i (rs11@[b0])) [@daemon] 
-     #Hcut >Hcut >(to_blank_i_chop  β€¦ b0 (a1::reverse β€¦ls10)) [2: @Hb0blank]
-     >to_blank_i_def >to_blank_i_def @eq_f 
-     >trace_def >trace_def @injective_reverse >reverse_map >reverse_cons
-     >reverse_reverse >reverse_map >reverse_append >reverse_single @sym_eq
-     @(proj1 β€¦ H3)
-    ]
-  |(*we do not find the head: this is absurd *)
-   * #b1 * #lss * * #H2 @False_ind 
-   cut (βˆ€x0. mem ? x0 (trace sig n n (b0::reverse ? rss@ls2)) β†’ x0 β‰  head ?)
-     [@daemon] -H2 #H2
-   lapply (trace_shift_neq sig n i n β€¦ lt_in β€¦ Hrss)
-     [@lt_to_not_eq @lt_in | // ] 
-   #H3 @(absurd 
-        (nth n ? (vec β€¦ (hd ? (ls1@[b]) (all_blank sig n))) (blank ?) = head ?))
-     [>Hhead //
-     |@H2 >trace_def %2 <map_append @mem_append_l1 <reverse_map <trace_def 
-      >H3 >H1 >trace_def >reverse_map >reverse_cons >reverse_append 
-      >reverse_reverse >associative_append <map_append @mem_append_l2
-      cases ls1 [%1 % |#x #ll %1 %]
-     ]
-   ]
- ]
-qed.