(** The language of Bellantoni and Cook *)

Require Import Bool Arith List.
Require Import BellantoniCook.Lib BellantoniCook.Bitstring BellantoniCook.MultiPoly.

(** * Syntax and induction principle

  - [BC_ind2] is a handmade induction principle because the one generated automatically by Coq
    ignores the types [list BC] in the constructor [comp].
*)

Inductive BC : Set :=
| zero : BC
| proj : nat -> nat -> nat -> BC
| succ : bool -> BC
| pred : BC
| cond : BC
| rec : BC -> BC -> BC -> BC
| comp : nat -> nat -> BC -> list BC -> list BC -> BC.  

Lemma BC_ind2' :
  forall P : BC -> Prop,
  forall Q : list BC -> Prop,
  Q nil ->
  (forall e l, P e -> Q l -> Q (e :: l)) ->
  P zero ->
  (forall n s i, P (proj n s i)) ->
  (forall b, P (succ b)) ->
  P pred ->
  P cond ->
  (forall g h0 h1, P g -> P h0 -> P h1 -> P (rec g h0 h1)) ->
  (forall n s h rl tl, P h -> Q rl -> Q tl ->
    P (comp n s h rl tl)) ->
  forall e, P e.
Proof.
(* Goal: forall (P : forall _ : BC, Prop) (Q : forall _ : list BC, Prop) (_ : Q (@nil BC)) (_ : forall (e : BC) (l : list BC) (_ : P e) (_ : Q l), Q (@cons BC e l)) (_ : P zero) (_ : forall n s i : nat, P (proj n s i)) (_ : forall b : bool, P (succ b)) (_ : P pred) (_ : P cond) (_ : forall (g h0 h1 : BC) (_ : P g) (_ : P h0) (_ : P h1), P (rec g h0 h1)) (_ : forall (n s : nat) (h : BC) (rl tl : list BC) (_ : P h) (_ : Q rl) (_ : Q tl), P (comp n s h rl tl)) (e : BC), P e *)
 fix BC_ind2' 12; intros.
(* Goal: P e *)
 destruct e; auto.
(* Goal: P (rec e1 e2 e3) *)
(* Goal: P (comp n n0 e l l0) *)
 apply H6; eapply BC_ind2'; eauto.
(* Goal: P (comp n n0 e l l0) *)
 apply H7.
(* Goal: P b *)
(* Goal: Q l0 *)
 eapply BC_ind2'; eauto.
(* Goal: Q l *)
(* Goal: Q l0 *)
 revert l.
(* Goal: forall l0 : list BC, Q l0 *)
 fix BC_ind2'0 1.
(* Goal: forall l0 : list BC, Q l0 *)
 intro.
(* Goal: Q n O l *)
(* Goal: Q n s l0 *)
 destruct l.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
(* Goal: Q (@cons BC b l0) *)
 apply H0.
(* Goal: P b *)
(* Goal: Q l0 *)
 eapply BC_ind2'; eauto.
(* Goal: Q l0 *)
 apply BC_ind2'0.
(* Goal: Q l0 *)
 revert l0.
(* Goal: forall l0 : list BC, Q l0 *)
 fix BC_ind2'0 1.
(* Goal: forall l0 : list BC, Q l0 *)
 intro.
(* Goal: Q n s l0 *)
 destruct l0.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
(* Goal: Q (@cons BC b l0) *)
 apply H0.
(* Goal: P b *)
(* Goal: Q l0 *)
 eapply BC_ind2'; eauto.
(* Goal: Q l0 *)
 apply BC_ind2'0.
Qed.

Lemma BC_ind2 :
  forall P : BC -> Prop,
  P zero ->
  (forall n s i, P (proj n s i)) ->
  (forall b, P (succ b)) ->
  P pred ->
  P cond ->
  (forall g h0 h1, P g -> P h0 -> P h1 -> P (rec g h0 h1)) ->
  (forall n s h rl tl, P h -> (forall r, In r rl -> P r) -> 
    (forall s, In s tl -> P s) ->
    P (comp n s h rl tl)) ->
  forall e, P e.
Proof.
(* Goal: forall (P : forall _ : BC, Prop) (_ : P zero) (_ : forall n s i : nat, P (proj n s i)) (_ : forall b : bool, P (succ b)) (_ : P pred) (_ : P cond) (_ : forall (g h0 h1 : BC) (_ : P g) (_ : P h0) (_ : P h1), P (rec g h0 h1)) (_ : forall (n s : nat) (h : BC) (rl tl : list BC) (_ : P h) (_ : forall (r : BC) (_ : @In BC r rl), P r) (_ : forall (s0 : BC) (_ : @In BC s0 tl), P s0), P (comp n s h rl tl)) (e : BC), P e *)
  intros; apply BC_ind2' with (Q := fun l => forall e, In e l -> P e); intros; auto; simpl in *.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  tauto.
(* Goal: P e1 *)
  destruct H8.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  subst; auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  auto.
Qed.

(** * Arities

  - [arities e] returns the arities (i.e., the number of normal and safe variables)
    of the expression [e] if it is well formed, or an error including the arities of the subterms.
*)

Inductive Arities : Set :=
| error_rec : Arities -> Arities -> Arities -> Arities
| error_comp : Arities -> list Arities -> list Arities -> Arities
| error_proj : nat -> nat -> nat -> Arities
| ok_arities : nat -> nat -> Arities.

Definition aeq (x y:Arities) : bool :=
  match x, y with
  | ok_arities xn xs, ok_arities yn ys => beq_nat xn yn && beq_nat xs ys
  | _, _ => false
  end.

Lemma aeq_eq (x y : Arities) :
  aeq x y = true -> x = y.
Proof.
(* Goal: forall _ : @eq bool (aeq x y) true, @eq Arities x y *)
  destruct x; destruct y; simpl; intros; try discriminate.
(* Goal: @eq Arities (ok_arities n n0) (ok_arities n1 n2) *)
  apply andb_true_iff in H; destruct H.
(* Goal: @eq Arities (ok_arities n n0) (ok_arities n1 n2) *)
  apply beq_nat_true in H.
(* Goal: @eq Arities (ok_arities n n0) (ok_arities n1 n2) *)
  apply beq_nat_true in H0.
(* Goal: @eq Arities (ok_arities n n0) (ok_arities n1 n2) *)
  subst; trivial.
Qed.  

Lemma aeq_eq_conv xn yn xs ys :
  aeq (ok_arities xn xs) (ok_arities yn ys) = false -> xn <> yn \/ xs <> ys.
Proof.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
  simpl; intros.
(* Goal: or (not (@eq nat xn yn)) (not (@eq nat xs ys)) *)
  apply andb_false_elim in H.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  destruct H as [H | H]; apply beq_nat_false in H; tauto.
Qed.

Fixpoint arities (e:BC) : Arities :=
  match e with
  | zero => ok_arities 0 0
  | proj n s i => 
    if leb (S i) (n + s) then ok_arities n s
      else error_proj n s i
  | succ _ => ok_arities 0 1
  | pred => ok_arities 0 1
  | cond => ok_arities 0 4
  | rec g h0 h1 =>
      match arities g, arities h0, arities h1 
        with | ok_arities gn gs, ok_arities h0n h0s, ok_arities h1n h1s =>
          if beq_nat (S gn) h0n && beq_nat h0n h1n &&
            beq_nat (S gs) h0s && beq_nat h0s h1s 
          then ok_arities h0n gs 
            else error_rec (ok_arities gn gs) (ok_arities h0n h0s) (ok_arities h1n h1s)
        | e1, e2, e3 => error_rec e1 e2 e3
      end
    | comp n s h nl sl =>
      match arities h, map arities nl, map arities sl with
      | ok_arities hn hs, anl, asl =>
        if beq_nat hn (length nl) && beq_nat hs (length sl) && 
          forallb (fun ne => aeq (arities ne) (ok_arities n 0)) nl &&
          forallb (fun se => aeq (arities se) (ok_arities n s)) sl
          then ok_arities n s
          else error_comp (ok_arities hn hs) anl asl 
      | e , anl, asl => error_comp e anl asl
      end
  end.

Definition arities2 e :=
  match arities e with
    | ok_arities n s => (n, s)
    | _ => (0, 0)
  end.

Lemma proj_arities : forall n s i, 
  i < n+s -> 
  arities (proj n s i) = ok_arities n s.
Proof.
(* Goal: forall (n s i : nat) (_ : lt i (Init.Nat.add n s)), @eq Arities (arities (proj n s i)) (ok_arities n s) *)
 intros n s i Hi; simpl.
(* Goal: @eq Arities (if match Init.Nat.add n s with | O => false | S m' => Nat.leb i m' end then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
 case_eq (n+s).
(* Goal: forall _ : @eq nat (Init.Nat.add n s) O, @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
 intro H; contradict Hi; omega.
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
 intros ns Hns.
(* Goal: @eq Arities (if Nat.leb i ns then ok_arities n s else error_proj n s i) (ok_arities n s) *)
 case_eq (leb i ns); intros H0.
(* Goal: @eq Arities (ok_arities n s) (ok_arities n s) *)
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
 apply leb_complete in H0; trivial.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
 apply leb_complete_conv in H0; contradict Hi; omega.
Qed.

Lemma comp_arities : forall n s e nel sel,
  arities e = ok_arities (length nel) (length sel) ->
  andl (fun ne => arities ne = ok_arities n 0) nel ->
  andl (fun se => arities se = ok_arities n s) sel ->
  arities (comp n s e nel sel) = ok_arities n s.
Proof.
(* Goal: forall (n s : nat) (e : BC) (nel sel : list BC) (_ : @eq Arities (arities e) (ok_arities (@length BC nel) (@length BC sel))) (_ : @andl BC (fun ne : BC => @eq Arities (arities ne) (ok_arities n O)) nel) (_ : @andl BC (fun se : BC => @eq Arities (arities se) (ok_arities n s)) sel), @eq Arities (arities (comp n s e nel sel)) (ok_arities n s) *)
 intros b s e nel sel He Hnel Hsel; simpl.
(* Goal: @eq Arities match arities e with | error_rec a a0 a1 => error_comp (error_rec a a0 a1) (@map BC Arities arities nel) (@map BC Arities arities sel) | error_comp a l l0 => error_comp (error_comp a l l0) (@map BC Arities arities nel) (@map BC Arities arities sel) | error_proj n n0 n1 => error_comp (error_proj n n0 n1) (@map BC Arities arities nel) (@map BC Arities arities sel) | ok_arities hn hs => if andb (andb (andb (Nat.eqb hn (@length BC nel)) (Nat.eqb hs (@length BC sel))) (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel)) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities hn hs) (@map BC Arities arities nel) (@map BC Arities arities sel) end (ok_arities b s) *)
 rewrite He.
(* Goal: @eq Arities (if andb (andb (andb (Nat.eqb (@length BC nel) (@length BC nel)) (Nat.eqb (@length BC sel) (@length BC sel))) (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel)) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 rewrite <- !beq_nat_refl.
(* Goal: @eq Arities (if andb (andb (andb true true) (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel)) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 case_eq (forallb (fun ne : BC => aeq (arities ne) (ok_arities b 0)) nel).
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) true, @eq Arities (if andb (andb (andb true true) true) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 intros _.
(* Goal: @eq Arities (if andb (andb (andb true true) true) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 case_eq (forallb (fun se : BC => aeq (arities se) (ok_arities b s)) sel).
(* Goal: forall _ : @eq bool (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) true, @eq Arities (if andb (andb (andb true true) true) true then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) false, @eq Arities (if andb (andb (andb true true) true) false then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 intros _; trivial.
(* Goal: forall _ : @eq bool (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) false, @eq Arities (if andb (andb (andb true true) true) false then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 intro Hsel'.
(* Goal: @eq Arities (if andb (andb (andb true true) true) false then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 rewrite forallb_forall_conv in Hsel'.
(* Goal: @eq Arities (if andb (andb (andb true true) true) false then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 destruct Hsel' as [e' [H1 H2] ].
(* Goal: @eq Arities (error_proj O O i) (ok_arities O O) *)
(* Goal: @eq Arities (if Nat.leb i n then ok_arities (S n) O else error_proj (S n) O i) (ok_arities (S n) O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
 contradict H2.
(* Goal: not (@eq bool (aeq (arities e') (ok_arities b s)) false) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 rewrite <- forall_andl in Hsel.
(* Goal: not (@eq bool (aeq (arities e') (ok_arities b s)) false) *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 rewrite Hsel; simpl.
(* Goal: not (@eq bool (andb (Nat.eqb b b) (Nat.eqb s s)) false) *)
(* Goal: @In BC e' sel *)
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 do 2 rewrite <- beq_nat_refl.
(* Goal: @eq (list bool) (sem h0 (@app (list bool) (@cons (list bool) v vnl) (@repeat (list bool) match @length (list bool) (@cons (list bool) v vnl) with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@app (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) (@repeat (list bool) match @length (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) with | O => S s | S l => Init.Nat.sub s l end (@nil bool)))) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
 simpl; congruence.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 trivial.
(* Goal: forall _ : @eq bool (@forallb BC (fun ne : BC => aeq (arities ne) (ok_arities b O)) nel) false, @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 intro Hnel'.
(* Goal: @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 rewrite forallb_forall_conv in Hnel'.
(* Goal: @eq Arities (if andb (andb (andb true true) false) (@forallb BC (fun se : BC => aeq (arities se) (ok_arities b s)) sel) then ok_arities b s else error_comp (ok_arities (@length BC nel) (@length BC sel)) (@map BC Arities arities nel) (@map BC Arities arities sel)) (ok_arities b s) *)
 destruct Hnel' as [e' [H1 H2] ].
(* Goal: @eq Arities (error_proj O O i) (ok_arities O O) *)
(* Goal: @eq Arities (if Nat.leb i n then ok_arities (S n) O else error_proj (S n) O i) (ok_arities (S n) O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
 contradict H2.
(* Goal: not (@eq bool (aeq (arities e') (ok_arities b O)) false) *)
 rewrite <- forall_andl in Hnel.
(* Goal: not (@eq bool (aeq (arities e') (ok_arities b O)) false) *)
 rewrite Hnel.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
 simpl.
(* Goal: not (@eq bool (andb (Nat.eqb b b) true) false) *)
(* Goal: @In BC e' nel *)
 rewrite <- beq_nat_refl.
(* Goal: @eq (list bool) (sem h0 (@app (list bool) (@cons (list bool) v vnl) (@repeat (list bool) match @length (list bool) (@cons (list bool) v vnl) with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@app (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) (@repeat (list bool) match @length (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) with | O => S s | S l => Init.Nat.sub s l end (@nil bool)))) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
 simpl; congruence.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 trivial.
Qed.

Lemma arities_nth :
  forall l i e n s,
  (forall e, In e l -> arities e = ok_arities n s) ->
  arities e = ok_arities n s ->
  arities (nth i l e) = ok_arities n s.
Proof.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
induction l as [ | e1 l IH]; simpl; intros [ | i]; trivial; auto.
Qed.

Lemma BC_ind_inf' :
  forall (P : nat -> nat -> BC -> Prop),
  forall Q : nat -> nat -> list BC -> Prop,
  (forall n s, Q n s nil) ->
  (forall e n s l, P n s e -> Q n s l -> Q n s (e :: l)) ->
  P 0 0 zero ->
  (forall n s i, i < n + s ->  P n s (proj n s i)) ->
  (forall b, P 0 1 (succ b)) ->
  P 0 1 pred ->
  P 0 4 cond ->
  (forall n s g h0 h1, 
    arities g = ok_arities n s ->
    arities h0 = ok_arities (S n) (S s) ->
    arities h1 = ok_arities (S n) (S s) ->
    P n s g -> 
    P (S n) (S s) h0 -> 
    P (S n) (S s) h1 -> 
    P (S n) s (rec g h0 h1)) ->
  (forall n s h rl tl, 
    arities h = ok_arities (length rl) (length tl) ->
    (forall e, In e rl -> arities e = ok_arities n 0) ->
    (forall e, In e tl -> arities e = ok_arities n s) ->
    P (length rl) (length tl) h -> 
    Q n 0 rl -> 
    Q n s tl ->
    P n s (comp n s h rl tl)) ->
  forall e n s , arities e = ok_arities n s -> P n s e.
Proof.
(* Goal: forall (P : forall (_ : nat) (_ : nat) (_ : BC), Prop) (Q : forall (_ : nat) (_ : nat) (_ : list BC), Prop) (_ : forall n s : nat, Q n s (@nil BC)) (_ : forall (e : BC) (n s : nat) (l : list BC) (_ : P n s e) (_ : Q n s l), Q n s (@cons BC e l)) (_ : P O O zero) (_ : forall (n s i : nat) (_ : lt i (Init.Nat.add n s)), P n s (proj n s i)) (_ : forall b : bool, P O (S O) (succ b)) (_ : P O (S O) pred) (_ : P O (S (S (S (S O)))) cond) (_ : forall (n s : nat) (g h0 h1 : BC) (_ : @eq Arities (arities g) (ok_arities n s)) (_ : @eq Arities (arities h0) (ok_arities (S n) (S s))) (_ : @eq Arities (arities h1) (ok_arities (S n) (S s))) (_ : P n s g) (_ : P (S n) (S s) h0) (_ : P (S n) (S s) h1), P (S n) s (rec g h0 h1)) (_ : forall (n s : nat) (h : BC) (rl tl : list BC) (_ : @eq Arities (arities h) (ok_arities (@length BC rl) (@length BC tl))) (_ : forall (e : BC) (_ : @In BC e rl), @eq Arities (arities e) (ok_arities n O)) (_ : forall (e : BC) (_ : @In BC e tl), @eq Arities (arities e) (ok_arities n s)) (_ : P (@length BC rl) (@length BC tl) h) (_ : Q n O rl) (_ : Q n s tl), P n s (comp n s h rl tl)) (e : BC) (n s : nat) (_ : @eq Arities (arities e) (ok_arities n s)), P n s e *)
 fix BC_ind_inf' 12; intros.
(* Goal: P n s e *)
 destruct e; simpl in *.
 
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 injection H8; intros; subst; auto.

(* Goal: P n s (proj n0 n1 n2) *)
(* Goal: P n s (succ b) *)
(* Goal: P n s pred *)
(* Goal: P n s cond *)
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 case_eq (n0 + n1); intros; rewrite H9 in H8; try discriminate.
(* Goal: P n s (proj n0 n1 n2) *)
(* Goal: P n s (succ b) *)
(* Goal: P n s pred *)
(* Goal: P n s cond *)
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 case_eq (leb n2 n3); intros; rewrite H10 in H8; try discriminate.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 injection H8; intros; subst; auto.
(* Goal: P n s (proj n s n2) *)
(* Goal: P n s (succ b) *)
(* Goal: P n s pred *)
(* Goal: P n s cond *)
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply H2.
(* Goal: lt n2 (Init.Nat.add n s) *)
(* Goal: P n s (succ b) *)
(* Goal: P n s pred *)
(* Goal: P n s cond *)
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply leb_complete in H10; omega.

(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 injection H8; intros; subst; auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 injection H8; intros; subst; auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 injection H8; intros; subst; auto.

 case_eq (arities e1); intros; rewrite H9 in H8;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
 case_eq (arities e2); intros; rewrite H10 in H8;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
 case_eq (arities e3); intros; rewrite H11 in H8;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 destruct n2; simpl in *; try discriminate.
 case_eq (beq_nat n0 n2); intros; rewrite H12 in H8; simpl in *;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply beq_nat_true in H12; subst.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 destruct n4; simpl in *; try discriminate.
 case_eq (beq_nat n2 n4); intros; rewrite H12 in H8; simpl in *;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply beq_nat_true in H12; subst.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 destruct n3; simpl in *; try discriminate.
 case_eq (beq_nat n1 n3); intros; rewrite H12 in H8; simpl in *;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply beq_nat_true in H12; subst.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 destruct n5; simpl in *; try discriminate.
 case_eq (beq_nat n3 n5); intros; rewrite H12 in H8; simpl in *;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply beq_nat_true in H12; subst.
(* Goal: P n s (comp n0 n1 e l l0) *)
 injection H8; intros; subst.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 apply (@H6 n4 s); auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 eapply BC_ind_inf'; eauto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 eapply BC_ind_inf'; eauto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 eapply BC_ind_inf'; eauto.

 case_eq (arities e); intros; rewrite H9 in H8;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
 case_eq (beq_nat n2 (length l)); intros; rewrite H10 in H8;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply beq_nat_true in H10.
 case_eq (beq_nat n3 (length l0)); intros; rewrite H11 in H8;
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
   try discriminate.
(* Goal: P n s (comp n0 n1 e l l0) *)
 apply beq_nat_true in H11.
 case_eq (forallb (fun ne : BC => aeq (arities ne) 
   (ok_arities n0 0)) l); intros; rewrite H12 in H8; 
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
 try discriminate.
 case_eq (forallb (fun se : BC => aeq (arities se) 
   (ok_arities n0 n1)) l0); intros; rewrite H13 in H8; 
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
 try discriminate.
(* Goal: P n s (comp n0 n1 e l l0) *)
 simpl in H8.
(* Goal: P n s (comp n0 n1 e l l0) *)
 injection H8; intros; subst.

(* Goal: P n s (comp n s e l l0) *)
 rewrite forallb_forall in H12.
(* Goal: P n s (comp n s e l l0) *)
 rewrite forallb_forall in H13.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 apply H7; trivial.
(* Goal: forall (e : BC) (_ : @In BC e l0), @eq Arities (arities e) (ok_arities n s) *)
(* Goal: P (@length BC l) (@length BC l0) e *)
(* Goal: Q n O l *)
(* Goal: Q n s l0 *)
 intros; apply aeq_eq.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 apply H12; trivial.
(* Goal: forall (e : BC) (_ : @In BC e l0), @eq Arities (arities e) (ok_arities n s) *)
(* Goal: P (@length BC l) (@length BC l0) e *)
(* Goal: Q n O l *)
(* Goal: Q n s l0 *)
 intros; apply aeq_eq.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 apply H13; trivial.

(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 eapply BC_ind_inf'; eauto.

(* Goal: Q n s l0 *)
 clear H9.
(* Goal: Q n O l *)
(* Goal: Q n s l0 *)
 revert l H12.
(* Goal: forall (l0 : list BC) (_ : forall (x : BC) (_ : @In BC x l0), @eq bool (aeq (arities x) (ok_arities n s)) true), Q n s l0 *)
 fix BC_ind_inf'0 1.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: Q n O l *)
(* Goal: Q n s l0 *)
 destruct l.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
(* Goal: Q (@cons BC b l0) *)
 eapply H0.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 eapply BC_ind_inf'; eauto.
(* Goal: @eq Arities (arities b) (ok_arities n s) *)
(* Goal: Q n s l0 *)
 apply aeq_eq.
(* Goal: @eq bool (aeq (arities x) (ok_arities n O)) true *)
(* Goal: Q n s l0 *)
 apply H12.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 simpl; auto.
(* Goal: Q n s l0 *)
 apply BC_ind_inf'0.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: @eq bool (aeq (arities x) (ok_arities n O)) true *)
(* Goal: Q n s l0 *)
 apply H12.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 simpl; auto.
(* Goal: Q n s l0 *)
 clear H9.
(* Goal: Q n s l0 *)
 revert l0 H13.
(* Goal: forall (l0 : list BC) (_ : forall (x : BC) (_ : @In BC x l0), @eq bool (aeq (arities x) (ok_arities n s)) true), Q n s l0 *)
 fix BC_ind_inf'0 1.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: Q n s l0 *)
 destruct l0.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
(* Goal: Q (@cons BC b l0) *)
 eapply H0.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 eapply BC_ind_inf'; eauto.
(* Goal: @eq Arities (arities b) (ok_arities n s) *)
(* Goal: Q n s l0 *)
 apply aeq_eq.
(* Goal: @eq bool (aeq (arities x) (ok_arities n s)) true *)
 apply H13.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 simpl; auto.
(* Goal: Q n s l0 *)
 apply BC_ind_inf'0.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: @eq bool (aeq (arities x) (ok_arities n s)) true *)
 apply H13.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 simpl; auto.
Qed.

Lemma BC_ind_inf :
  forall (P : nat -> nat -> BC -> Prop),
  P 0 0 zero ->
  (forall n s i, i < n + s ->  P n s (proj n s i)) ->
  (forall b, P 0 1 (succ b)) ->
  P 0 1 pred ->
  P 0 4 cond ->
  (forall n s g h0 h1, 
    arities g = ok_arities n s ->
    arities h0 = ok_arities (S n) (S s) ->
    arities h1 = ok_arities (S n) (S s) ->
    P n s g -> 
    P (S n) (S s) h0 -> 
    P (S n) (S s) h1 -> 
    P (S n) s (rec g h0 h1)) ->
  (forall n s h rl tl, 
    arities h = ok_arities (length rl) (length tl) ->
    (forall e, In e rl -> arities e = ok_arities n 0) ->
    (forall e, In e tl -> arities e = ok_arities n s) ->
    P (length rl) (length tl) h -> 
    (forall r, In r rl -> P n 0 r) ->
    (forall r, In r tl -> P n s r) ->
    P n s (comp n s h rl tl)) ->
  forall e n s , arities e = ok_arities n s -> P n s e.
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  intros.
  apply BC_ind_inf'
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
    with (Q := fun n s l => forall e , In e l -> P n s e); auto; simpl in *; intros.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  tauto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  destruct H9; subst; auto.
Qed.

(** * Semantics

  - [sem e vnl vsl] is the evaluation of the expression [e] where the [i]th normal variable is
    instantiated with the [i]th value of [vnl], and the [i]th safe variable is
    instantiated with the [i]th value of [vsl].
    If a variable is not assigned a value, then it is assumed to be the empty bitstring [nil].
    Values in [vnl] and [vsl] that do not correspond to a variable are ignored.

  - [BC_ind_inf] is an induction principle that makes easier dealing with arities in inductive proofs.
*)

Fixpoint sem_rec (sem_g sem_h0 sem_h1:list bs->list bs->bs)(v:bs)(vnl vsl:list bs) :=
  match v with
    | nil => sem_g vnl vsl
    | b::v' =>
      if b then sem_h1 (v'::vnl) (sem_rec sem_g sem_h0 sem_h1 v' vnl vsl :: vsl)
      else sem_h0 (v'::vnl) (sem_rec sem_g sem_h0 sem_h1 v' vnl vsl :: vsl)
  end.

Fixpoint sem (e:BC)(vnl vsl:list bs) : bs :=
  match e with
  | zero => nil
  | proj n s j => 
    if leb (S j) n then
      nth j vnl nil
      else nth (j-n) vsl nil
  | succ b => b :: hd nil vsl
  | pred => tail (hd nil vsl)
  | cond =>
      match vsl with
      | a :: b :: c :: d :: _ => 
        match a with 
          | nil => b
          | true :: _ => c
          | false :: _ => d
        end
      | a :: b :: c :: _ => 
        match a with 
          | nil => b
          | true :: _ => c
          | false :: _ => nil
        end
      | a :: b :: _ => 
        match a with 
          | nil => b
          | _ => nil
        end
      | _ => nil
      end
  | rec g h0 h1 => sem_rec (sem g) (sem h0) (sem h1) (hd nil vnl) (tail vnl) vsl
  | comp _ _ h nl sl => 
    sem h (List.map (fun ne => sem ne vnl nil) nl) 
          (List.map (fun se => sem se vnl vsl) sl)
  end.

Lemma sem_comp :
  forall n s f nel sel nl sl, 
  sem (comp n s f nel sel) nl sl =
  sem f (map (fun ne => sem ne nl nil) nel) (map (fun se => sem se nl sl) sel).
Proof.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 trivial.
Qed.

(** * Some properties of [cond] *)

Lemma cond_simpl_nil n s fn fc ff ft l1 l2 :
  sem fc l1 l2 = nil ->
  sem (comp n s cond nil [fc; fn; ft; ff]) l1 l2 = sem fn l1 l2.
Proof.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 simpl; intros; rewrite H; simpl; trivial.
Qed.

Lemma cond_simpl_notnil n s fn fc ft ff l1 l2 :
  sem fc l1 l2 <> nil ->
  sem (comp n s cond nil [fc; fn; ft; ff]) l1 l2 = 
  match sem fc l1 l2 with
    | nil => nil 
    | true :: _ => sem ft l1 l2 
    | false :: _ => sem ff l1 l2
  end.
Proof.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
  simpl; intros.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  destruct (sem fc l1 l2); intros; auto.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  elim H; trivial.
Qed.

Lemma cond_simpl_true n s fn fc ff ft l1 l2 :
  hd false (sem fc l1 l2) = true ->
  sem (comp n s cond nil [fc; fn; ft; ff]) l1 l2 = sem ft l1 l2.
Proof.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
 simpl; intros.
(* Goal: @eq (list bool) match sem fc l1 l2 with | nil => sem fn l1 l2 | cons (true as b) l => sem ft l1 l2 | cons (false as b) l => sem ff l1 l2 end (sem ft l1 l2) *)
 destruct (sem fc l1 l2).
(* Goal: @eq (list bool) (sem fn l1 l2) (sem ft l1 l2) *)
(* Goal: @eq (list bool) (if b then sem ft l1 l2 else sem ff l1 l2) (sem ft l1 l2) *)
 simpl in H.
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
 discriminate.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 destruct b; simpl in *; trivial.
(* Goal: @eq (list bool) (sem ff l1 l2) (sem ft l1 l2) *)
 discriminate.
Qed.

Lemma cond_simpl_false n s fn fc ff ft l1 l2 l :
  sem fc l1 l2 = false :: l ->
  sem (comp n s cond nil [fc; fn; ft; ff]) l1 l2 = sem ff l1 l2.
Proof.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
 simpl; intros.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 rewrite H; simpl; trivial.
Qed.

Lemma sem_nth :
  forall i start len f d vnl vsl,
  0 <= i < len ->
  sem (nth i (map f (seq start len)) d) vnl vsl = sem (f (i+start)) vnl vsl.
Proof.
(* Goal: forall (i start len : nat) (f : forall _ : nat, BC) (d : BC) (vnl vsl : list (list bool)) (_ : and (le O i) (lt i len)), @eq (list bool) (sem (@nth BC i (@map nat BC f (seq start len)) d) vnl vsl) (sem (f (Init.Nat.add i start)) vnl vsl) *)
intros i start len.
(* Goal: forall (f : forall _ : nat, BC) (d : BC) (vnl vsl : list (list bool)) (_ : and (le O i) (lt i len)), @eq (list bool) (sem (@nth BC i (@map nat BC f (seq start len)) d) vnl vsl) (sem (f (Init.Nat.add i start)) vnl vsl) *)
revert i start.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
induction len as [ | len IH]; simpl; intros.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
contradict H.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (@nth (list bool) i (@cons (list bool) v vnl) (@nil bool)) (@nth (list bool) i (@cons (list bool) v (@firstn (list bool) n vnl)) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
destruct i as [ | i].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S (S i)))) (seq (Init.Nat.add (S n) (S (S i))) s))) (@firstn (list bool) s (@skipn (list bool) (S i) vsl)) *)
(* Goal: @eq nat (S (S (Init.Nat.add n (S i)))) (Init.Nat.add (S n) (S (S i))) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
rewrite IH.
(* Goal: @eq (list bool) (sem (f (Init.Nat.add i (S start))) vnl vsl) (sem (f (Init.Nat.add (S i) start)) vnl vsl) *)
(* Goal: and (le O i) (lt i len) *)
do 2 f_equal.
(* Goal: @eq nat (S (S (Init.Nat.add n (S i)))) (Init.Nat.add (S n) (S (S i))) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
ring.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
Qed.

Lemma map_sem_nth :
  forall i f1 f2 vnl vsl d,
  map (fun f => sem f vnl vsl) f1 = map (fun f => sem f vnl vsl) f2 ->
  sem (nth i f1 d) vnl vsl = sem (nth i f2 d) vnl vsl.
Proof.
(* Goal: forall (i : nat) (f1 f2 : list BC) (vnl vsl : list (list bool)) (d : BC) (_ : @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) f1) (@map BC (list bool) (fun f : BC => sem f vnl vsl) f2)), @eq (list bool) (sem (@nth BC i f1 d) vnl vsl) (sem (@nth BC i f2 d) vnl vsl) *)
induction i as [ | i IH]; simpl; intros [ | e1 f1] [ | e2 f2] vnl vsl d H; simpl in *; trivial; try congruence.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (Init.Nat.add (S n) (S O)) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (S (Init.Nat.add n O))) (Init.Nat.add (S n) (S O)) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
apply IH.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
congruence.
Qed.

Lemma sem_proj_S_normal :
  forall n s i f vsl vnl,
  i < n ->
  sem (proj (S n) s (S i)) (f::vnl) vsl =
  sem (proj n s i) vnl vsl.
Proof.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
Qed.

Lemma sem_proj_S_safe :
  forall n s i f vsl vnl,
  n <= i ->
  sem (proj n (S s) (S i)) vnl (f::vsl) =
  sem (proj n s i) vnl vsl.
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list (list bool)) (@cons (list bool) (if match n with | O => false | S m' => Nat.leb (Init.Nat.add n i) m' end then @nth (list bool) (Init.Nat.add n i) vnl (@nil bool) else match Init.Nat.sub (Init.Nat.add n i) n with | O => v | S m => @nth (list bool) m vsl (@nil bool) end) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj n (S (Init.Nat.add s i))) (seq (S (Init.Nat.add n i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
destruct n as [ | n].
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list (list bool)) (@cons (list bool) (if match n with | O => false | S m' => Nat.leb (Init.Nat.add n i) m' end then @nth (list bool) (Init.Nat.add n i) vnl (@nil bool) else match Init.Nat.sub (Init.Nat.add n i) n with | O => v | S m => @nth (list bool) m vsl (@nil bool) end) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj n (S (Init.Nat.add s i))) (seq (S (Init.Nat.add n i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
destruct n as [ | n].
(* Goal: @eq (list bool) match Init.Nat.sub i O with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (if Nat.leb i O then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S O)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) (S i) vnl (@nil bool) else match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end) (if Nat.leb i (S n) then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
cutrewrite (i-0 = S (i-1)).
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S O)) vsl (@nil bool)) (if Nat.leb i O then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S O)) vsl (@nil bool)) *)
(* Goal: @eq nat (Init.Nat.sub i O) (S (Init.Nat.sub i (S O))) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) (S i) vnl (@nil bool) else match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end) (if Nat.leb i (S n) then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
case_eq (leb i 0); intro Hi.
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) i vnl (@nil bool)) *)
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
apply leb_complete in Hi.
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
contradict Hi.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) (S i) vnl (@nil bool) else match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end) (if Nat.leb i (S n) then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
case_eq (leb i n); intro Hi.
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) i vnl (@nil bool)) *)
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
apply leb_complete in Hi.
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
contradict Hi.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
clear Hi.
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (if Nat.leb i (S n) then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
case_eq (leb i (S n)); intro Hi.
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) i vnl (@nil bool)) *)
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
apply leb_complete in Hi.
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
contradict Hi.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
clear Hi.
(* Goal: @eq (list bool) match Init.Nat.sub i (S n) with | O => f | S m => @nth (list bool) m vsl (@nil bool) end (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
case_eq (i - S n).
(* Goal: forall _ : @eq nat (Init.Nat.sub i (S n)) O, @eq (list bool) f (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.sub i (S n)) (S n0)), @eq (list bool) (@nth (list bool) n0 vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
intro Hi.
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
contradict Hi.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.sub i (S n)) (S n0)), @eq (list bool) (@nth (list bool) n0 vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
intros j Hi.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
Qed.

Lemma sem_firstn_safe :
  forall f n s vnl vsl,
  arities f = ok_arities n s ->
  sem f vnl vsl = sem f vnl (firstn s vsl).
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
revert f n s H vnl vsl.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
refine (BC_ind_inf _ _ _ _ _ _ _ _); simpl; intros.

(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
destruct n as [ | n]; simpl in *; intros.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i O) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i O) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite <- minus_n_O.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@firstn (list bool) n vnl) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
rewrite nth_firstn.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
case_eq (leb i n); intro H0.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
destruct vnl as [ | v vnl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (@nth (list bool) i (@cons (list bool) v vnl) (@nil bool)) (@nth (list bool) i (@cons (list bool) v (@firstn (list bool) n vnl)) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
destruct i as [ | i].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@firstn (list bool) n vnl) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
apply leb_complete in H0.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@firstn (list bool) n vnl) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
rewrite nth_firstn.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: lt (Init.Nat.sub i (S n)) s *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) match vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@nil (list bool)) end)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) match vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@nil (list bool)) end)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match match vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a match l with | nil => @nil (list bool) | cons a0 l0 => @cons (list bool) a0 match l0 with | nil => @nil (list bool) | cons a1 l1 => @cons (list bool) a1 match l1 with | nil => @nil (list bool) | cons a2 l2 => @cons (list bool) a2 (@nil (list bool)) end end end end with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) (@firstn (list bool) s vsl)) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl (@firstn (list bool) s vsl)) tl)) *)
apply leb_complete_conv in H0.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.

(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons b (nil as l) => match v with | nil => b | cons b0 l0 => @nil bool end | cons b (cons c (nil as l0) as l) => match v with | nil => b | cons (true as b0) l1 => c | cons (false as b0) l1 => @nil bool end | cons b (cons c (cons d l1 as l0) as l) => match v with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => d end end match @app (list bool) (@cons (list bool) v vsl) (@repeat (list bool) match @length (list bool) (@cons (list bool) v vsl) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v' vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) match vsl with | nil => match v with | nil => v' | cons b l => @nil bool end | cons c (nil as l) => match v with | nil => v' | cons (true as b) l0 => c | cons (false as b) l0 => @nil bool end | cons c (cons d l0 as l) => match v with | nil => v' | cons (true as b) l1 => c | cons (false as b) l1 => d end end match @app (list bool) (@cons (list bool) v (@cons (list bool) v' vsl)) (@repeat (list bool) match @length (list bool) (@cons (list bool) v (@cons (list bool) v' vsl)) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v'' vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) match vsl with | nil => match v with | nil => v' | cons (true as b) l => v'' | cons (false as b) l => @nil bool end | cons d l => match v with | nil => v' | cons (true as b) l0 => v'' | cons (false as b) l0 => d end end match @app (list bool) (@cons (list bool) v (@cons (list bool) v' (@cons (list bool) v'' vsl))) (@repeat (list bool) match @length (list bool) (@cons (list bool) v (@cons (list bool) v' (@cons (list bool) v'' vsl))) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v''' vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct vnl as [ | v vnl]; simpl.
(* Goal: @eq (list bool) (@fst (list bool) nat (sem_cost h (@map (prod (list bool) nat) (list bool) (@fst (list bool) nat) (@map BC (prod (list bool) nat) (fun ne : BC => sem_cost ne vnl (@nil (list bool))) rl)) (@map (prod (list bool) nat) (list bool) (@fst (list bool) nat) (@map BC (prod (list bool) nat) (fun se : BC => sem_cost se vnl vsl) tl)))) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
rewrite H2.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
induction v as [ | [ | ] v IH]; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem h1 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h1 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h0 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite H4.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
congruence.
(* Goal: @eq (list bool) (sem h0 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite H3.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
congruence.

(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
clear H H2.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
apply map_ext2.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem a vnl vsl) (sem a vnl (@firstn (list bool) s vsl)) *)
apply H4.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
Qed.

Lemma sem_firstn_normal :
  forall f n s vnl vsl,
  arities f = ok_arities n s ->
  sem f vnl vsl = sem f (firstn n vnl) vsl.
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
revert f n s H vnl vsl.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
refine (BC_ind_inf _ _ _ _ _ _ _ _); simpl; intros.

(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
destruct n as [ | n]; simpl in *; intros.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i O) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i O) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite <- minus_n_O.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
case_eq (leb i n); intro H0.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
destruct vnl as [ | v vnl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (@nth (list bool) i (@cons (list bool) v vnl) (@nil bool)) (@nth (list bool) i (@cons (list bool) v (@firstn (list bool) n vnl)) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
destruct i as [ | i].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@firstn (list bool) n vnl) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
apply leb_complete in H0.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@firstn (list bool) n vnl) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
rewrite nth_firstn.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons b (nil as l) => match v with | nil => b | cons b0 l0 => @nil bool end | cons b (cons c (nil as l0) as l) => match v with | nil => b | cons (true as b0) l1 => c | cons (false as b0) l1 => @nil bool end | cons b (cons c (cons d l1 as l0) as l) => match v with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => d end end match @app (list bool) (@cons (list bool) v vsl) (@repeat (list bool) match @length (list bool) (@cons (list bool) v vsl) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v' vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) match vsl with | nil => match v with | nil => v' | cons b l => @nil bool end | cons c (nil as l) => match v with | nil => v' | cons (true as b) l0 => c | cons (false as b) l0 => @nil bool end | cons c (cons d l0 as l) => match v with | nil => v' | cons (true as b) l1 => c | cons (false as b) l1 => d end end match @app (list bool) (@cons (list bool) v (@cons (list bool) v' vsl)) (@repeat (list bool) match @length (list bool) (@cons (list bool) v (@cons (list bool) v' vsl)) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v'' vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) match vsl with | nil => match v with | nil => v' | cons (true as b) l => v'' | cons (false as b) l => @nil bool end | cons d l => match v with | nil => v' | cons (true as b) l0 => v'' | cons (false as b) l0 => d end end match @app (list bool) (@cons (list bool) v (@cons (list bool) v' (@cons (list bool) v'' vsl))) (@repeat (list bool) match @length (list bool) (@cons (list bool) v (@cons (list bool) v' (@cons (list bool) v'' vsl))) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v''' vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct vnl as [ | v vnl]; simpl.
(* Goal: @eq (list bool) (sem g (@nil (list bool)) vsl) (sem g (@nil (list bool)) vsl) *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) (sem_rec (sem g) (sem h0) (sem h1) v (@firstn (list bool) n vnl) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
rewrite H2, firstn_nil.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
induction v as [ | [ | ] v IH]; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem h1 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h1 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h0 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite H4.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
congruence.
(* Goal: @eq (list bool) (sem h0 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite H3.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
congruence.

(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
clear H H2.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
apply map_ext2.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
auto.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
apply map_ext2.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
auto.
Qed.


Lemma sem_firstn :
  forall f n s vnl vsl,
  arities f = ok_arities n s ->
  sem f vnl vsl = sem f (firstn n vnl) (firstn s vsl).
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
erewrite sem_firstn_safe; eauto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
erewrite sem_firstn_normal; eauto.
Qed.

Lemma sem_repeat :
  forall f vnl vsl n s,
  arities f = ok_arities n s ->
  sem f vnl vsl = sem f (vnl ++ repeat (n - length vnl) nil) (vsl ++ repeat (s - length vsl) nil).
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
revert f n s H vnl vsl.
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
refine (BC_ind_inf _ _ _ _ _ _ _ _); simpl; intros.

(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
destruct n as [ | n]; simpl in *; intros.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i O) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i O) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite <- minus_n_O.
(* Goal: @eq (list bool) (@nth (list bool) i vsl (@nil bool)) (@nth (list bool) i (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct (le_dec (length vsl) i).
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite app_nth2,nth_repeat, nth_overflow.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite app_nth1.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
case_eq (leb i n); intro Hleb.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct (le_dec (length vnl) i).
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite app_nth2,nth_repeat, nth_overflow.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: lt (Init.Nat.sub i (@length (list bool) vnl)) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end *)
(* Goal: ge i (@length (list bool) vnl) *)
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
apply leb_complete in Hleb.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
destruct (length vnl); omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite app_nth1.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct (le_dec (length vsl) (i - S n)).
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite app_nth2,nth_repeat, nth_overflow.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: lt (Init.Nat.sub (Init.Nat.sub i (S n)) (@length (list bool) vsl)) (Init.Nat.sub s (@length (list bool) vsl)) *)
(* Goal: ge (Init.Nat.sub i (S n)) (@length (list bool) vsl) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
apply leb_complete_conv in Hleb.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite app_nth1.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.

(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.

(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v vsl].
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons b (nil as l) => match v with | nil => b | cons b0 l0 => @nil bool end | cons b (cons c (nil as l0) as l) => match v with | nil => b | cons (true as b0) l1 => c | cons (false as b0) l1 => @nil bool end | cons b (cons c (cons d l1 as l0) as l) => match v with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => d end end match @app (list bool) (@cons (list bool) v vsl) (@repeat (list bool) match @length (list bool) (@cons (list bool) v vsl) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v' vsl].
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
destruct v as [ | [ | ] v]; trivial.
(* Goal: @eq (list bool) match vsl with | nil => match v with | nil => v' | cons b l => @nil bool end | cons c (nil as l) => match v with | nil => v' | cons (true as b) l0 => c | cons (false as b) l0 => @nil bool end | cons c (cons d l0 as l) => match v with | nil => v' | cons (true as b) l1 => c | cons (false as b) l1 => d end end match @app (list bool) (@cons (list bool) v (@cons (list bool) v' vsl)) (@repeat (list bool) match @length (list bool) (@cons (list bool) v (@cons (list bool) v' vsl)) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v'' vsl].
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
destruct v as [ | [ | ] v]; trivial.
(* Goal: @eq (list bool) match vsl with | nil => match v with | nil => v' | cons (true as b) l => v'' | cons (false as b) l => @nil bool end | cons d l => match v with | nil => v' | cons (true as b) l0 => v'' | cons (false as b) l0 => d end end match @app (list bool) (@cons (list bool) v (@cons (list bool) v' (@cons (list bool) v'' vsl))) (@repeat (list bool) match @length (list bool) (@cons (list bool) v (@cons (list bool) v' (@cons (list bool) v'' vsl))) with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
destruct vsl as [ | v''' vsl].
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
destruct v as [ | [ | ] v]; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
destruct v as [ | [ | ] v]; trivial.

(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct vnl as [ | v vnl]; simpl.
(* Goal: @eq (list bool) (@fst (list bool) nat (sem_cost h (@map (prod (list bool) nat) (list bool) (@fst (list bool) nat) (@map BC (prod (list bool) nat) (fun ne : BC => sem_cost ne vnl (@nil (list bool))) rl)) (@map (prod (list bool) nat) (list bool) (@fst (list bool) nat) (@map BC (prod (list bool) nat) (fun se : BC => sem_cost se vnl vsl) tl)))) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
rewrite H2.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list (list bool)) (@repeat (list bool) (Init.Nat.sub n O) (@nil bool)) (@repeat (list bool) n (@nil bool)) *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
cutrewrite (n-0 = n).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
induction v as [ | [ | ] v IH]; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem h1 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h1 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h0 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite H4.
(* Goal: @eq (list bool) (sem h0 (@app (list bool) (@cons (list bool) v vnl) (@repeat (list bool) match @length (list bool) (@cons (list bool) v vnl) with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@app (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) (@repeat (list bool) match @length (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) with | O => S s | S l => Init.Nat.sub s l end (@nil bool)))) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
simpl; congruence.
(* Goal: @eq (list bool) (sem h0 (@cons (list bool) v vnl) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl)) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite H3.
(* Goal: @eq (list bool) (sem h0 (@app (list bool) (@cons (list bool) v vnl) (@repeat (list bool) match @length (list bool) (@cons (list bool) v vnl) with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@app (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) (@repeat (list bool) match @length (list bool) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v vnl vsl) vsl) with | O => S s | S l => Init.Nat.sub s l end (@nil bool)))) (sem h0 (@cons (list bool) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@cons (list bool) (sem_rec (sem g) (sem h0) (sem h1) v (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
simpl; congruence.

(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
clear H H2.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
induction rl as [ | r rl IH]; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list bool) (sem r vnl (@nil (list bool))) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl) *)
apply H3.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
simpl; tauto.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (Init.Nat.add (S n) (S O)) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (S (Init.Nat.add n O))) (Init.Nat.add (S n) (S O)) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
apply IH.
(* Goal: forall (r : BC) (_ : @In BC r tl) (vnl vsl : list (list bool)), @eq (list bool) (sem r vnl vsl) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
auto with *.
(* Goal: forall (r : BC) (_ : @In BC r tl) (vnl vsl : list (list bool)), @eq (list bool) (sem r vnl vsl) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
auto with *.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
induction tl as [ | t tl IH]; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: forall (r : BC) (_ : @In BC r tl) (vnl vsl : list (list bool)), @eq (list bool) (sem r vnl vsl) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
auto with *.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (Init.Nat.add (S n) (S O)) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (S (Init.Nat.add n O))) (Init.Nat.add (S n) (S O)) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
apply IH.
(* Goal: forall (r : BC) (_ : @In BC r tl) (vnl vsl : list (list bool)), @eq (list bool) (sem r vnl vsl) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
auto with *.
(* Goal: forall (r : BC) (_ : @In BC r tl) (vnl vsl : list (list bool)), @eq (list bool) (sem r vnl vsl) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
auto with *.
Qed.

Lemma map_sem_repeat :
  forall fl vnl vsl n s,
  (forall f, In f fl -> arities f = ok_arities n s) ->
  map (fun f => sem f vnl vsl) fl =
  map (
    fun f =>
      sem f
        (vnl ++ repeat (n - length vnl) nil)
        (vsl ++ repeat (s - length vsl) nil)
  ) fl.
Proof.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
induction fl as [ | f fl IH]; intros vnl vsl n s H; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) fl) (@map BC (list bool) (fun f : BC => sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) fl) *)
apply sem_repeat.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
apply H; simpl; tauto.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (Init.Nat.add (S n) (S O)) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (S (Init.Nat.add n O))) (Init.Nat.add (S n) (S O)) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
apply IH.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq Arities (arities f0) (ok_arities n s) *)
apply H.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
simpl; tauto.
Qed.

Lemma map_proj_seq_normal_gen :
  forall n i vnl,
  n+i <= length vnl ->
  map (fun f : BC => sem f vnl nil) (map (proj (n+i) 0) (seq i n)) =
  firstn n (skipn i vnl).
Proof.
(* Goal: forall (n i : nat) (vnl : list (list bool)) (_ : le (Init.Nat.add n i) (@length (list bool) vnl)), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj (Init.Nat.add n i) O) (seq i n))) (@firstn (list bool) n (@skipn (list bool) i vnl)) *)
induction n as [ | n IH]; simpl; intros i vnl Hn.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) (if Nat.leb i (Init.Nat.add n i) then @nth (list bool) i vnl (@nil bool) else match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
destruct vnl as [ | v vnl]; simpl in *.
(* Goal: @eq (list (list bool)) (@cons (list bool) match i with | O => @nil bool | S m => @nil bool end (@firstn (list bool) n (@nil (list bool)))) match @skipn (list bool) i (@nil (list bool)) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match i with | O => v1 | S m => @nth (list bool) m vnl (@nil bool) end (@firstn (list bool) n (@skipn (list bool) i vnl))) match @skipn (list bool) i (@cons (list bool) v1 vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
(* Goal: le (Init.Nat.add n (S (S i))) (@length (list bool) (@cons (list bool) v vnl)) *)
(* Goal: @eq nat (S (Init.Nat.add n (S i))) (Init.Nat.add n (S (S i))) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
contradict Hn.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: forall _ : @eq nat (Init.Nat.sub i (S n)) O, @eq (list bool) f (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.sub i (S n)) (S n0)), @eq (list bool) (@nth (list bool) n0 vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S (S n))) vsl (@nil bool)) *)
case_eq (leb i (n+i)); intro Hi.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct i as [ | i]; simpl.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n O)) O) (seq (S O) n))) (@firstn (list bool) n vnl) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vnl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n (S i))) O) (seq (S (S i)) n)))) match @skipn (list bool) i vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
cutrewrite (S (n+0) = n+1).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (Init.Nat.add (S n) (S O)) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (S (Init.Nat.add n O))) (Init.Nat.add (S n) (S O)) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
apply IH.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
simpl; omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vnl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n (S i))) O) (seq (S (S i)) n)))) match @skipn (list bool) i vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
cutrewrite (S (n + S i) = n + S (S i)).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S (S i)))) (seq (Init.Nat.add (S n) (S (S i))) s))) (@firstn (list bool) s (@skipn (list bool) (S i) vsl)) *)
(* Goal: @eq nat (S (S (Init.Nat.add n (S i)))) (Init.Nat.add (S n) (S (S i))) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
rewrite IH.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vnl (@nil bool)) (@firstn (list bool) n match vnl with | nil => @nil (list bool) | cons a l => @skipn (list bool) i l end)) match @skipn (list bool) i vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
(* Goal: le (Init.Nat.add n (S (S i))) (@length (list bool) (@cons (list bool) v vnl)) *)
(* Goal: @eq nat (S (Init.Nat.add n (S i))) (Init.Nat.add n (S (S i))) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
destruct vnl as [ | v1 vnl]; simpl in *.
(* Goal: @eq (list (list bool)) (@cons (list bool) match i with | O => @nil bool | S m => @nil bool end (@firstn (list bool) n (@nil (list bool)))) match @skipn (list bool) i (@nil (list bool)) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match i with | O => v1 | S m => @nth (list bool) m vnl (@nil bool) end (@firstn (list bool) n (@skipn (list bool) i vnl))) match @skipn (list bool) i (@cons (list bool) v1 vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
(* Goal: le (Init.Nat.add n (S (S i))) (@length (list bool) (@cons (list bool) v vnl)) *)
(* Goal: @eq nat (S (Init.Nat.add n (S i))) (Init.Nat.add n (S (S i))) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
contradict Hn.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct i as [ | i]; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
rewrite <- cons_skipn with (d:=nil).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
simpl; omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
apply leb_complete_conv in Hi.
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub i (S (Init.Nat.add n i)) with | O => @nil bool | S m => @nil bool end (@map BC (list bool) (fun f : BC => sem f (@cons (list bool) v vnl) (@nil (list bool))) (@map nat BC (proj (S (Init.Nat.add n i)) O) (seq (S i) n)))) match @skipn (list bool) i (@cons (list bool) v vnl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end *)
contradict Hi.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
Qed.

Lemma map_proj_seq_normal :
  forall n vnl,
  map (fun f : BC => sem f vnl nil) (map (proj n 0) (seq 0 n)) =
  firstn n vnl ++ repeat (n - length vnl) nil.
Proof.
(* Goal: forall (n : nat) (vnl : list (list bool)), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
intros n vnl.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
destruct (le_gt_dec (n+0) (length vnl)) as [H | H].
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
cutrewrite (n - length vnl = 0).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) O (@nil bool))) *)
(* Goal: @eq nat (Init.Nat.sub n (@length (list bool) vnl)) O *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
generalize (map_proj_seq_normal_gen n 0 vnl H).
(* Goal: @eq (list (list bool)) (@app (list bool) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) (@nil (list bool))) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
simpl_list.
(* Goal: @eq Arities (if match Init.Nat.add n O with | O => false | S m' => Nat.leb i m' end then ok_arities n O else error_proj n O i) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
rewrite <- plus_n_O.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
transitivity (firstn n (vnl ++ repeat (n - length vnl) nil)).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
assert (n + 0 <= length (vnl ++ repeat (n - length vnl) nil)) as H0.
(* Goal: le (Init.Nat.add s O) (@length (list bool) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite app_length.
(* Goal: le (Init.Nat.add s O) (Init.Nat.add (@length (list bool) vsl) (@length (list bool) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite length_repeat.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
generalize (map_proj_seq_normal_gen n 0 (vnl ++ repeat (n - length vnl) nil) H0).
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq Arities (if match Init.Nat.add n O with | O => false | S m' => Nat.leb i m' end then ok_arities n O else error_proj n O i) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
rewrite <- plus_n_O.
(* Goal: forall _ : @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intro H1.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite <- H1.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
clear H H0 H1.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) (@map BC (list bool) (fun f : BC => sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) (@map nat BC (proj n O) (seq O n))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
rewrite map_sem_repeat with (n:=n) (s:=0).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: forall (f : BC) (_ : @In BC f (@map nat BC (proj n O) (seq O n))), @eq Arities (arities f) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
intros f H.
(* Goal: @eq Arities (arities f) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
rewrite in_map_iff in H.
(* Goal: @eq Arities (arities f) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
destruct H as [i [H1 H2] ].
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite in_seq_iff in H2.
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
subst f.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq Arities (if match Init.Nat.add n O with | O => false | S m' => Nat.leb i m' end then ok_arities n O else error_proj n O i) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
rewrite <- plus_n_O.
(* Goal: @eq nat (@fst nat (list mon) (if match n with | O => false | S m' => Nat.leb i m' end then pproj n i else pcst n O)) n *)
(* Goal: @eq nat match match Init.Nat.max (@fst nat (list mon) (poly_BC (S n) h0)) (@fst nat (list mon) (poly_BC (S n) h1)) with | O => S n | S m' => S (Init.Nat.max n m') end with | O => S (@fst nat (list mon) (poly_BC (Init.Nat.sub n O) g)) | S m' => S (Init.Nat.max (@fst nat (list mon) (poly_BC (Init.Nat.sub n O) g)) m') end (S n) *)
(* Goal: @eq nat (Init.Nat.max n (Init.Nat.max (maxl (@map (prod nat (list mon)) nat (@fst nat (list mon)) (@map BC pol (poly_BC n) rl))) (@fst nat (list mon) (pplusl (@map BC pol (poly_BC n) tl))))) n *)
destruct n.
(* Goal: @eq Arities (error_proj O O i) (ok_arities O O) *)
(* Goal: @eq Arities (if Nat.leb i n then ok_arities (S n) O else error_proj (S n) O i) (ok_arities (S n) O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
contradict H2.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq Arities (if Nat.leb i n then ok_arities (S n) O else error_proj (S n) O i) (ok_arities (S n) O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
case_eq (leb i n).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: forall _ : @eq nat (Init.Nat.add n s) O, @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intro H.
(* Goal: @eq Arities (error_proj (S n) O i) (ok_arities (S n) O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
rewrite leb_iff_conv in H.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
contradict H.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
clear H.
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
revert vnl.
(* Goal: forall vnl : list (list bool), @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
induction n as [ | n IH]; simpl in *; intro vnl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct vnl; simpl.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nil bool) (@firstn (list bool) s (@repeat (list bool) s (@nil bool)))) (@cons (list bool) (@nil bool) (@repeat (list bool) s (@nil bool))) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
clear IH.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@repeat (list bool) s (@nil bool))) (@repeat (list bool) s (@nil bool)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
apply firstn_repeat_le.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
congruence.
Qed.

Lemma map_proj_seq_safe_gen :
  forall n s i vnl vsl,
  s+i <= length vsl ->
  map (fun f : BC => sem f vnl vsl) (map (proj n (s+i)) (seq (n+i) s)) =
  firstn s (skipn i vsl).
Proof.
(* Goal: forall (n s i : nat) (vnl vsl : list (list bool)) (_ : le (Init.Nat.add s i) (@length (list bool) vsl)), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n (Init.Nat.add s i)) (seq (Init.Nat.add n i) s))) (@firstn (list bool) s (@skipn (list bool) i vsl)) *)
intros n s.
(* Goal: forall (i : nat) (vnl vsl : list (list bool)) (_ : le (Init.Nat.add s i) (@length (list bool) vsl)), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n (Init.Nat.add s i)) (seq (Init.Nat.add n i) s))) (@firstn (list bool) s (@skipn (list bool) i vsl)) *)
revert n.
(* Goal: forall (n i : nat) (vnl vsl : list (list bool)) (_ : le (Init.Nat.add s i) (@length (list bool) vsl)), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n (Init.Nat.add s i)) (seq (Init.Nat.add n i) s))) (@firstn (list bool) s (@skipn (list bool) i vsl)) *)
induction s as [ | s IH]; simpl; intros n i vnl vsl Hs.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) (if match n with | O => false | S m' => Nat.leb (Init.Nat.add n i) m' end then @nth (list bool) (Init.Nat.add n i) vnl (@nil bool) else @nth (list bool) (Init.Nat.sub (Init.Nat.add n i) n) vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n (S (Init.Nat.add s i))) (seq (S (Init.Nat.add n i)) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
destruct vsl as [ | v vsl]; simpl in *.
(* Goal: @eq (list (list bool)) (@cons (list bool) (if match n with | O => false | S m' => Nat.leb (Init.Nat.add n i) m' end then @nth (list bool) (Init.Nat.add n i) vnl (@nil bool) else match Init.Nat.sub (Init.Nat.add n i) n with | O => @nil bool | S m => @nil bool end) (@map BC (list bool) (fun f : BC => sem f vnl (@nil (list bool))) (@map nat BC (proj n (S (Init.Nat.add s i))) (seq (S (Init.Nat.add n i)) s)))) match @skipn (list bool) i (@nil (list bool)) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (if match n with | O => false | S m' => Nat.leb (Init.Nat.add n i) m' end then @nth (list bool) (Init.Nat.add n i) vnl (@nil bool) else match Init.Nat.sub (Init.Nat.add n i) n with | O => v | S m => @nth (list bool) m vsl (@nil bool) end) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj n (S (Init.Nat.add s i))) (seq (S (Init.Nat.add n i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
contradict Hs.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list (list bool)) (@cons (list bool) (if match n with | O => false | S m' => Nat.leb (Init.Nat.add n i) m' end then @nth (list bool) (Init.Nat.add n i) vnl (@nil bool) else match Init.Nat.sub (Init.Nat.add n i) n with | O => v | S m => @nth (list bool) m vsl (@nil bool) end) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj n (S (Init.Nat.add s i))) (seq (S (Init.Nat.add n i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
destruct n as [ | n].
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub (Init.Nat.add O i) O with | O => v | S m => @nth (list bool) m vsl (@nil bool) end (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj O (S (Init.Nat.add s i))) (seq (S (Init.Nat.add O i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (if Nat.leb (Init.Nat.add (S n) i) n then @nth (list bool) (Init.Nat.add (S n) i) vnl (@nil bool) else match Init.Nat.sub (Init.Nat.add (S n) i) (S n) with | O => v | S m => @nth (list bool) m vsl (@nil bool) end) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s i))) (seq (S (Init.Nat.add (S n) i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
cutrewrite (0+i-0 = i).
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct i as [ |i]; simpl.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s O))) (seq (S (S (Init.Nat.add n O))) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
cutrewrite (S (s+0) = s+1).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (Init.Nat.add (S n) (S O)) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (S (Init.Nat.add n O))) (Init.Nat.add (S n) (S O)) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
apply IH.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
simpl; omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
rewrite <- cons_skipn with (d:=nil).
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s))) (@firstn (list bool) s (@skipn (list bool) (S i) vsl)) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
cutrewrite (S (s + S i) = s + S (S i)).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S (S i)))) (seq (Init.Nat.add (S n) (S (S i))) s))) (@firstn (list bool) s (@skipn (list bool) (S i) vsl)) *)
(* Goal: @eq nat (S (S (Init.Nat.add n (S i)))) (Init.Nat.add (S n) (S (S i))) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
rewrite IH.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
simpl; omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: forall _ : @eq nat (Init.Nat.add n s) O, @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
case_eq (leb (S n + i) n); intro H.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) (Init.Nat.add (S n) i) vnl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s i))) (seq (S (Init.Nat.add (S n) i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub (Init.Nat.add (S n) i) (S n) with | O => v | S m => @nth (list bool) m vsl (@nil bool) end (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s i))) (seq (S (Init.Nat.add (S n) i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
apply leb_complete in H.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
contradict H.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list (list bool)) (@cons (list bool) match Init.Nat.sub (Init.Nat.add (S n) i) (S n) with | O => v | S m => @nth (list bool) m vsl (@nil bool) end (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s i))) (seq (S (Init.Nat.add (S n) i)) s)))) match @skipn (list bool) i (@cons (list bool) v vsl) with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
cutrewrite (S n + i - S n = i).
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct i as [ | i]; simpl.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s O))) (seq (S (S (Init.Nat.add n O))) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
cutrewrite (S (s+0) = s+1).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (S (S (Init.Nat.add n O))) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
cutrewrite (S (S (n+0)) = S n + 1).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S O))) (seq (Init.Nat.add (S n) (S O)) s))) (@firstn (list bool) s vsl) *)
(* Goal: @eq nat (S (S (Init.Nat.add n O))) (Init.Nat.add (S n) (S O)) *)
(* Goal: @eq nat (S (Init.Nat.add s O)) (Init.Nat.add s (S O)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
apply IH.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
simpl; omega.
(* Goal: @eq nat (S (S (Init.Nat.add n (S i)))) (Init.Nat.add (S n) (S (S i))) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
ring.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nth (list bool) i vsl (@nil bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s)))) match @skipn (list bool) i vsl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) s l) end *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
rewrite <- cons_skipn with (d:=nil).
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (S (Init.Nat.add s (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s))) (@firstn (list bool) s (@skipn (list bool) (S i) vsl)) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
cutrewrite (S (s + S i) = s + S (S i)).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S (S i)))) (seq (S (S (Init.Nat.add n (S i)))) s))) (@firstn (list bool) s (@skipn (list bool) (S i) vsl)) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
cutrewrite (S (S (n + S i)) = (S n + S (S i))).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@cons (list bool) v vsl)) (@map nat BC (proj (S n) (Init.Nat.add s (S (S i)))) (seq (Init.Nat.add (S n) (S (S i))) s))) (@firstn (list bool) s (@skipn (list bool) (S i) vsl)) *)
(* Goal: @eq nat (S (S (Init.Nat.add n (S i)))) (Init.Nat.add (S n) (S (S i))) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
rewrite IH.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
simpl; omega.
(* Goal: @eq nat (S (S (Init.Nat.add n (S i)))) (Init.Nat.add (S n) (S (S i))) *)
(* Goal: @eq nat (S (Init.Nat.add s (S i))) (Init.Nat.add s (S (S i))) *)
(* Goal: lt i (@length (list bool) vsl) *)
(* Goal: @eq nat (Init.Nat.sub (Init.Nat.add (S n) i) (S n)) i *)
ring.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
Qed.

Lemma map_proj_seq_safe :
  forall n s vnl vsl,
  map (fun f : BC => sem f vnl vsl) (map (proj n s) (seq n s)) =
  firstn s vsl ++ repeat (s - length vsl) nil.
Proof.
(* Goal: forall (n s : nat) (vnl vsl : list (list bool)), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intros n s vnl vsl.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
destruct (le_gt_dec (s+0) (length vsl)) as [H | H].
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
cutrewrite (s - length vsl = 0).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) O (@nil bool))) *)
(* Goal: @eq nat (Init.Nat.sub s (@length (list bool) vsl)) O *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
generalize (map_proj_seq_safe_gen n s 0 vnl vsl H).
(* Goal: @eq (list (list bool)) (@app (list bool) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) (@nil (list bool))) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
simpl_list.
(* Goal: @eq Arities (if match Init.Nat.add n O with | O => false | S m' => Nat.leb i m' end then ok_arities n O else error_proj n O i) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
do 2 rewrite <- plus_n_O.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.

(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
transitivity (firstn s (vsl ++ repeat (s - length vsl) nil)).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
assert (s + 0 <= length (vsl ++ repeat (s - length vsl) nil)) as H0.
(* Goal: le (Init.Nat.add s O) (@length (list bool) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite app_length.
(* Goal: le (Init.Nat.add s O) (Init.Nat.add (@length (list bool) vsl) (@length (list bool) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite length_repeat.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
generalize (map_proj_seq_safe_gen n s 0 vnl (vsl ++ repeat (s - length vsl) nil) H0).
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq Arities (if match Init.Nat.add n O with | O => false | S m' => Nat.leb i m' end then ok_arities n O else error_proj n O i) (ok_arities n O) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) n (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) n vnl) (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) *)
do 2 rewrite <- plus_n_O.
(* Goal: forall _ : @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))), @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intro H1.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite <- H1.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
clear H H0 H1.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun f : BC => sem f vnl vsl) (@map nat BC (proj n s) (seq n s))) (@map BC (list bool) (fun f : BC => sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@map nat BC (proj n s) (seq n s))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
apply map_ext2.
(* Goal: forall (a : BC) (_ : @In BC a (@map nat BC (proj n s) (seq n s))), @eq (list bool) (sem a vnl vsl) (sem a vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intros f Hf.
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite in_map_iff in Hf.
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
destruct Hf as [i [H1 H2] ].
(* Goal: @eq (list bool) (sem f vnl vsl) (sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite in_seq_iff in H2.
(* Goal: @eq (list bool) (sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite sem_repeat with (n:=n) (s:=s).
(* Goal: @eq (list bool) (sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
symmetry.
(* Goal: @eq (list bool) (sem f vnl (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (sem f (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite sem_repeat with (n:=n) (s:=s).
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@app (list bool) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite <- app_assoc.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
transitivity (repeat (s - length vsl) nil (A:=list bool) ++  nil).
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@nil bool)) (@nil (list bool)) *)
(* Goal: @eq (list (list bool)) (@app (list bool) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) (@nil (list bool))) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite app_length, length_repeat.
(* Goal: @eq (list (list bool)) (@repeat (list bool) (Init.Nat.sub s (Init.Nat.add (@length (list bool) vsl) (Init.Nat.sub s (@length (list bool) vsl)))) (@nil bool)) (@nil (list bool)) *)
(* Goal: @eq (list (list bool)) (@app (list bool) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) (@nil (list bool))) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
cutrewrite (s - (length vsl + (s - length vsl)) = 0).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list (list bool)) (@app (list bool) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) (@nil (list bool))) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
simpl_list.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
subst f.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq Arities (if match Init.Nat.add n s with | O => false | S m' => Nat.leb i m' end then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
case_eq (n+s).
(* Goal: forall _ : @eq nat (Init.Nat.add n s) O, @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intro H.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
contradict H.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intros p H.
(* Goal: @eq Arities (if Nat.leb i p then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
case_eq (leb i p).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: forall _ : @eq bool (Nat.leb i p) false, @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intro Hleb.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite leb_iff_conv in Hleb.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
contradict Hleb.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq Arities (arities f) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
subst f.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
(* Goal: @eq Arities (if match Init.Nat.add n s with | O => false | S m' => Nat.leb i m' end then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
case_eq (n+s).
(* Goal: forall _ : @eq nat (Init.Nat.add n s) O, @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intro H.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
contradict H.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: forall (n0 : nat) (_ : @eq nat (Init.Nat.add n s) (S n0)), @eq Arities (if Nat.leb i n0 then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intros p H.
(* Goal: @eq Arities (if Nat.leb i p then ok_arities n s else error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
case_eq (leb i p).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: forall _ : @eq bool (Nat.leb i p) false, @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
intro Hleb.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
rewrite leb_iff_conv in Hleb.
(* Goal: @eq Arities (error_proj n s i) (ok_arities n s) *)
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
contradict Hleb.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
clear H.
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
revert vsl.
(* Goal: forall vsl : list (list bool), @eq (list (list bool)) (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) *)
induction s as [ | s IH]; simpl in *; intro vsl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct vsl; simpl.
(* Goal: @eq (list (list bool)) (@cons (list bool) (@nil bool) (@firstn (list bool) s (@repeat (list bool) s (@nil bool)))) (@cons (list bool) (@nil bool) (@repeat (list bool) s (@nil bool))) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
clear IH.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
f_equal.
(* Goal: @eq (list (list bool)) (@firstn (list bool) s (@repeat (list bool) s (@nil bool))) (@repeat (list bool) s (@nil bool)) *)
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
apply firstn_repeat_le.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
trivial.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
congruence.
Qed.

Definition zero_e (n s:nat) : BC :=
  comp n s zero nil nil.

Lemma sem_comp_proj_normal : forall n1 n2 f1 vnl i,
n2 <> 0 -> i < n2 ->
sem (comp n1 0 (proj n2 0 i) f1 nil) vnl nil =
sem (nth i f1 (zero_e n1 0)) vnl nil.
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
 simpl.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
 destruct n2; simpl.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 elim H; auto.
(* Goal: @eq (list bool) (if Nat.leb i n2 then @nth (list bool) i (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) f1) (@nil bool) else match Init.Nat.sub i (S n2) with | O => @nil bool | S m => @nil bool end) (sem (@nth BC i f1 (zero_e n1 O)) vnl (@nil (list bool))) *)
 rewrite leb_correct; [ | omega].
(* Goal: @eq (list bool) (@nth (list bool) i (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) f1) (@nil bool)) (sem (@nth BC i f1 (zero_e n1 O)) vnl (@nil (list bool))) *)
 rewrite map_nth2 with (d := zero_e n1 0).
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 simpl; auto.
Qed.

Lemma sem_comp_proj_safe : forall n1 s1 n2 s2 f1 f2 vnl vsl i,
n2 <= i ->
sem (comp n1 s1 (proj n2 s2 i) f1 f2) vnl vsl =
sem (nth (i - n2) f2 (zero_e n1 s1)) vnl vsl.
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
 simpl.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
 destruct n2; simpl.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n2)) (@map BC (list bool) (fun se : BC => sem se vnl vsl) f2) (@nil bool)) (sem (@nth BC (Init.Nat.sub i (S n2)) f2 (zero_e n1 s1)) vnl vsl) *)
 rewrite map_nth2 with (d := (zero_e n1 s1)).
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 simpl; auto.
(* Goal: @eq (list bool) (@nth (list bool) n0 ls (@nil bool)) (if Nat.leb a (S n) then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S (S n))) ls (@nil bool)) *)
 rewrite leb_correct_conv; [ | omega].
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n2)) (@map BC (list bool) (fun se : BC => sem se vnl vsl) f2) (@nil bool)) (sem (@nth BC (Init.Nat.sub i (S n2)) f2 (zero_e n1 s1)) vnl vsl) *)
 rewrite map_nth2 with (d := zero_e n1 s1).
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 auto.
Qed.

(** * Polymax Bounding

  - The lemma [polymax_bounding] states that the output of an expression [e] with [n] normal variables
    is bounded by the sum of the polynomial [poly_BC n e] and of the size of its longest safe input.
*)

Fixpoint poly_BC n (e : BC) : pol :=
  match e with 
    | zero => pcst 0 0
    | proj n s i => if (leb (S i) n) then pproj n i else (pcst n 0)
    | succ b => pcst 0 1
    | pred => pcst 0 0
    | cond => pcst 0 0
    | rec g h0 h1 =>
        pplus (pshift (poly_BC (n - 1) g)) 
        (pmult (pproj n 0) (pplus (poly_BC n h0) (poly_BC n h1)))
    | comp n s h rl tl =>
      (pplus (pcst n 0)
        (pplus (pcomp (poly_BC (length rl) h) (map (poly_BC n) rl ))
          (pplusl (map (poly_BC n) tl))))
  end.

Lemma arity_poly_BC : forall e n s,
  arities e = ok_arities n s ->
  parity (poly_BC n e) = n.
Proof.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  apply BC_ind_inf; simpl; intros; auto.
(* Goal: @eq nat (@fst nat (list mon) (if match n with | O => false | S m' => Nat.leb i m' end then pproj n i else pcst n O)) n *)
(* Goal: @eq nat match match Init.Nat.max (@fst nat (list mon) (poly_BC (S n) h0)) (@fst nat (list mon) (poly_BC (S n) h1)) with | O => S n | S m' => S (Init.Nat.max n m') end with | O => S (@fst nat (list mon) (poly_BC (Init.Nat.sub n O) g)) | S m' => S (Init.Nat.max (@fst nat (list mon) (poly_BC (Init.Nat.sub n O) g)) m') end (S n) *)
(* Goal: @eq nat (Init.Nat.max n (Init.Nat.max (maxl (@map (prod nat (list mon)) nat (@fst nat (list mon)) (@map BC pol (poly_BC n) rl))) (@fst nat (list mon) (pplusl (@map BC pol (poly_BC n) tl))))) n *)
  destruct n.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  rewrite parity_pcst; trivial.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  case_eq (leb i n); intros.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  rewrite parity_pproj; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  rewrite parity_pcst; trivial.
(* Goal: @eq nat match match Init.Nat.max (@fst nat (list mon) (poly_time (S n) h0)) (@fst nat (list mon) (poly_time (S n) h1)) with | O => S n | S m' => S (Init.Nat.max n m') end with | O => S (@fst nat (list mon) (poly_time (Init.Nat.sub n O) g)) | S m' => S (Init.Nat.max (@fst nat (list mon) (poly_time (Init.Nat.sub n O) g)) m') end (S n) *)
(* Goal: @eq nat (Init.Nat.max (Init.Nat.max n (maxl (@map (prod nat (list mon)) nat (@fst nat (list mon)) (@map BC pol (poly_BC n) rl)))) (Init.Nat.max (@fst nat (list mon) (pplusl (@map BC pol (poly_time n) rl))) (@fst nat (list mon) (pplusl (@map BC pol (poly_time n) tl))))) n *)
  rewrite H3, H4, <- minus_n_O, H2.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  repeat rewrite Nat.max_idempotent; trivial.
(* Goal: @eq nat (Init.Nat.max n (Init.Nat.max (maxl (@map (prod nat (list mon)) nat (@fst nat (list mon)) (@map BC pol (poly_BC n) rl))) (@fst nat (list mon) (pplusl (@map BC pol (poly_BC n) tl))))) n *)
  apply max_l.
(* Goal: le (Init.Nat.max (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) rl)) (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl))) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  apply Nat.max_lub.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  apply maxl_map; intros.
(* Goal: le e' (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  rewrite in_map_iff in H5.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  destruct H5 as [p [Hp1 Hp2]]; subst; auto.
(* Goal: le (@fst nat (list mon) (pplusl (@map BC pol (poly_BC n) tl))) n *)
  rewrite parity_pplusl.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  apply maxl_map; intros.
(* Goal: le e' (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  rewrite in_map_iff in H5.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  destruct H5 as [p [Hp1 Hp2]]; subst; auto.
Qed.

Lemma pWF_poly_BC : forall e n s,
  arities e = ok_arities n s -> pWF (poly_BC n e).
Proof.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  apply BC_ind_inf; simpl; intros; auto; try pWF; auto.
(* Goal: pWF (if match n with | O => false | S m' => Nat.leb i m' end then pproj n i else pcst n O) *)
(* Goal: pWF (poly_BC (Init.Nat.sub n O) g) *)
(* Goal: pWF x *)
(* Goal: pWF x *)
  destruct n; [ pWF | ].
(* Goal: pWF (if Nat.leb i n then pproj (S n) i else pcst (S n) O) *)
(* Goal: pWF (poly_BC (Init.Nat.sub n O) g) *)
(* Goal: pWF x *)
(* Goal: pWF x *)
  case_eq (leb i n); intros; pWF.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  apply leb_complete in H0; omega.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  rewrite <- minus_n_O; auto.
(* Goal: le e' (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  rewrite in_map_iff in H5.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  destruct H5 as [p [Hp1 Hp2]]; subst; auto.
(* Goal: le e' (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  rewrite in_map_iff in H5.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  destruct H5 as [p [Hp1 Hp2]]; subst; auto.
Qed.
  
Lemma polymax_bounding : forall (e : BC) xl yl n s,
  arities e = ok_arities n s ->
  length (sem e xl yl) <= 
  peval (poly_BC n e) (map (@length _) xl) + maxl (map (@length _) yl).
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  intros.
  revert e n s H xl yl.
  refine (BC_ind_inf ((fun n s e => forall xl yl : list bs,
   length (sem e xl yl) <=
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
   peval (poly_BC n e) (map (@length _) xl) + maxl (map (@length _) yl))) _ _ _ _ _ _ _); simpl; intros.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  omega.  
(* Goal: @eq nat (@fst nat (list mon) (if match n with | O => false | S m' => Nat.leb i m' end then pproj n i else pcst n O)) n *)
(* Goal: @eq nat match match Init.Nat.max (@fst nat (list mon) (poly_BC (S n) h0)) (@fst nat (list mon) (poly_BC (S n) h1)) with | O => S n | S m' => S (Init.Nat.max n m') end with | O => S (@fst nat (list mon) (poly_BC (Init.Nat.sub n O) g)) | S m' => S (Init.Nat.max (@fst nat (list mon) (poly_BC (Init.Nat.sub n O) g)) m') end (S n) *)
(* Goal: @eq nat (Init.Nat.max n (Init.Nat.max (maxl (@map (prod nat (list mon)) nat (@fst nat (list mon)) (@map BC pol (poly_BC n) rl))) (@fst nat (list mon) (pplusl (@map BC pol (poly_BC n) tl))))) n *)
  destruct n.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  eapply le_trans;[ apply nth_maxl_bound | ]; trivial.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  case_eq (leb i n); intros.
(* Goal: @eq (list bool) (@nth (list bool) i vnl (@nil bool)) (@nth (list bool) i (@firstn (list bool) n vnl) (@nil bool)) *)
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) vsl)) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) (@tl (list bool) match vnl with | nil => @nil (list bool) | cons a l => @cons (list bool) a (@firstn (list bool) n l) end) vsl) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@firstn (list bool) n vnl) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@firstn (list bool) n vnl) vsl) tl)) *)
  apply leb_complete in H0.
  revert i H H0.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  induction xl; simpl; intros; simpl; destruct i; simpl; try omega.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  rewrite pproj_correct; simpl; omega.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  eapply le_trans;[ apply IHxl | ]; trivial; omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  eapply le_trans;[ apply nth_maxl_bound | ]; trivial.
  
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  rewrite hd_nth_0; apply le_n_S; apply nth_maxl_bound; trivial.
  
  eapply le_trans;[ | apply nth_maxl_bound].
  instantiate (1:=nil).
  rewrite hd_nth_0.
  instantiate (1:= 0).
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  destruct (@nth (list bool) Datatypes.O yl (@nil bool)); simpl; omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  trivial.
  
  do 3 (destruct yl; simpl; try omega).
  destruct l; simpl; auto with arith.
  destruct yl.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  destruct l; simpl.
  auto with arith.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  destruct b; simpl.
  rewrite Nat.max_0_r.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  case_eq (max (length l0) (length l1)); intros.
  apply Nat.max_lub_r with (n := length l0).
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  rewrite H;  omega.
  rewrite Nat.succ_max_distr, <- H.
  eapply le_trans;[ | apply Nat.le_max_r].
  apply Nat.le_max_r.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  destruct l; simpl.
(* Goal: le n (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  apply Nat.le_max_l.
  destruct b; simpl;
    case_eq ( max (length l0)
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
      (max (length l1) (max (length l2) (maxl (map (@length _) yl))))); intros.
  apply Nat.max_lub_l with (m := length l2).
  apply Nat.max_lub_r with (n := length l0).
  apply Nat.max_lub_l with (m := (maxl (map (@length _) yl))).
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  rewrite <- Nat.max_assoc, <- Nat.max_assoc, H; omega.
  rewrite Nat.succ_max_distr, <- H.
  eapply le_trans;[ | apply Nat.le_max_r].
  eapply le_trans;[ | apply Nat.le_max_r].
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  eapply le_trans;[ | apply Nat.le_max_l]; auto.
  apply Nat.max_lub_r with (n := length l1).
  apply Nat.max_lub_r with (n := length l0).
  apply Nat.max_lub_l with (m := (maxl (map (@length _) yl))).
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  rewrite <- Nat.max_assoc, <- Nat.max_assoc, H; omega.
  rewrite Nat.succ_max_distr, <- H.
  eapply le_trans;[ | apply Nat.le_max_r].
  eapply le_trans;[ | apply Nat.le_max_r].
  eapply le_trans;[ | apply Nat.le_max_r].
(* Goal: le n (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  apply Nat.le_max_l.

(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i O) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i O) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
  simpl; rewrite <- minus_n_O.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  destruct xl as [ | z xl]; simpl.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  eapply le_trans;[ apply H2 |]; simpl.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  rewrite pplus_correct, pmult_correct, pshift_correct; simpl; omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  induction z as [ | i z IHz ]; simpl.
  eapply le_trans; [apply H2 |].
  rewrite pplus_correct, pshift_correct; simpl; auto with arith.
  
  set (qh1 := peval (poly_BC (S n) h1) (length z :: map (@length _) xl)).
  set (qh0 := peval (poly_BC (S n) h0) (length z :: map (@length _) xl)).
  set (qg := peval (poly_BC n g)  (map (@length _) xl)).
  set (qh1S := 
    peval (poly_BC (S n) h1) (S (length z) :: map (@length _) xl)).
  set (qh0S := 
    peval (poly_BC (S n) h0) (S (length z) :: map (@length _) xl)).
  assert (qh1 <= qh1S).
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
  apply peval_monotonic; simpl; intros.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  case i0; trivial; omega.
  assert (qh0 <= qh0S).
(* Goal: forall _ : @eq (list bool) (sem fc l1 l2) (@cons bool false l), @eq (list bool) (sem (comp n s cond (@nil BC) (@cons BC fc (@cons BC fn (@cons BC ft (@cons BC ff (@nil BC)))))) l1 l2) (sem ff l1 l2) *)
  apply peval_monotonic; simpl; intros.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  case i0; trivial; omega.
  assert ( length z * (qh0 + qh1) <=  length z * (qh0S + qh1S)).
  apply mult_le_compat_l.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  omega.

  case i.
  eapply le_trans.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  eapply H4; eauto.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  simpl.
  eapply le_trans.
  apply plus_le_compat_l.
  apply Nat.max_le_compat_r.
  apply IHz.
  rewrite max_l; auto with arith.
  rewrite pplus_correct, pplus_correct, pmult_correct, pmult_correct, pplus_correct, pplus_correct,
    pshift_correct, pshift_correct, pproj_correct, pproj_correct; simpl;
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
      unfold qh0, qh1, qh0S, qh1S in *; omega.

  eapply le_trans.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  eapply H3; eauto.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  simpl.
  eapply le_trans.
  apply plus_le_compat_l.
  apply Nat.max_le_compat_r.
  apply IHz.
  rewrite max_l; auto with arith.
  rewrite pplus_correct, pplus_correct, pmult_correct, pmult_correct, pplus_correct, pplus_correct,
    pshift_correct, pshift_correct, pproj_correct, pproj_correct; simpl;
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
      unfold qh0, qh1, qh0S, qh1S in *; omega.

(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  rewrite pplus_correct, pcst_correct, pplus_correct, pcomp_correct, map_map; simpl.
  eapply le_trans.
(* Goal: P n s (proj n s n2) *)
(* Goal: P n s (succ b) *)
(* Goal: P n s pred *)
(* Goal: P n s cond *)
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
  apply H2.
  rewrite <- plus_assoc.
  apply plus_le_compat.
  rewrite map_map.
  apply peval_monotonic.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  intros.
  destruct (lt_dec i (length rl)).
  erewrite map_nth2.
  eapply le_trans.
(* Goal: @eq (list bool) (sem r vnl (@nil (list bool))) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) *)
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl) *)
  eapply H3.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  apply nth_In; trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
  simpl.
  rewrite plus_0_r.
  erewrite (@map_nth2 _ _ _ _ 0 _ i).
  apply le_refl.
  instantiate (1 := zero).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  simpl; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  simpl; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  rewrite nth_overflow, nth_overflow; trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  rewrite map_length; omega.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  rewrite map_length; omega.
  edestruct maxl_nth.
  destruct (lt_dec x (length tl)).
  rewrite H5. 
  erewrite map_nth2.
  eapply le_trans.
  erewrite map_nth2.
(* Goal: @eq (list bool) (sem a vnl vsl) (sem a vnl (@firstn (list bool) s vsl)) *)
  eapply H4.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  apply nth_In; trivial.
  instantiate (2 := zero).
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  simpl; trivial.
  apply plus_le_compat_r.
  erewrite <- (@map_nth2 _ _ (poly_BC n)).
  apply peval_nth_pplus.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  simpl; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  simpl; trivial.
  rewrite nth_overflow in H5.
  rewrite H5.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  omega.
  rewrite map_length, map_length.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
  omega.
Qed.

Lemma proj_seq_shift_safe : forall n m ln ls d,
 map (fun x : BC => sem x ln (d :: ls)) (map (proj n (S m)) (seq (S n) m)) =
 map (fun x : BC => sem x ln ls) (map (proj n m) (seq n m)).
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 rewrite <- seq_shift.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (@map nat nat S (seq O n)))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 rewrite map_map with (f := S).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x ln (@cons (list bool) d ls)) (@map nat BC (fun x : nat => proj n (S m) (S x)) (seq n m))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n m) (seq n m))) *)
 rewrite map_map with (f := (proj n m)).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x ln (@cons (list bool) d ls)) (@map nat BC (fun x : nat => proj n (S m) (S x)) (seq n m))) (@map nat (list bool) (fun x : nat => sem (proj n m x) ln ls) (seq n m)) *)
 rewrite map_map with (f := (fun x : nat => proj n (S m) (S x))).
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 apply map_ext2; intros.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
 simpl.
(* Goal: @eq (list bool) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) *)
 rewrite in_seq_iff in H.
(* Goal: @eq (list bool) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) *)
 destruct n; simpl in *.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 rewrite <- minus_n_O; trivial.
(* Goal: @eq (list bool) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) *)
 destruct n; simpl in *.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 rewrite <- minus_n_O; trivial.
(* Goal: @eq (list bool) match a with | O => d | S m => @nth (list bool) m ls (@nil bool) end (if Nat.leb a O then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S O)) ls (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) (S a) ln (@nil bool) else match Init.Nat.sub a (S n) with | O => d | S m => @nth (list bool) m ls (@nil bool) end) (if Nat.leb a (S n) then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S (S n))) ls (@nil bool)) *)
 destruct a; simpl in *.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
 elimtype False; omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 rewrite <- minus_n_O; trivial.
(* Goal: @eq (list bool) (@nth (list bool) n0 ls (@nil bool)) (if Nat.leb a (S n) then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S (S n))) ls (@nil bool)) *)
 rewrite leb_correct_conv; [ | omega ].
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 case_eq (a - S n); intros.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
 elimtype False; omega.
(* Goal: @eq (list bool) (@nth (list bool) n0 ls (@nil bool)) (if Nat.leb a (S n) then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S (S n))) ls (@nil bool)) *)
 rewrite leb_correct_conv; [ | omega ].
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
 f_equal.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
 omega.
Qed.

Lemma proj_seq_shift_normal : forall n ln ls d,
 map (fun x : BC => sem x (d :: ln) ls) (map (proj (S n) 0) (seq 1 n)) =
 map (fun x : BC => sem x ln ls) (map (proj n 0) (seq 0 n)).
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 intros.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 rewrite <- seq_shift.
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (@map nat nat S (seq O n)))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 rewrite map_map with (f := S).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (fun x : nat => proj (S n) O (S x)) (seq O n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 rewrite map_map with (f := (proj n 0)).
(* Goal: @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (fun x : nat => proj (S n) O (S x)) (seq O n))) (@map nat (list bool) (fun x : nat => sem (proj n O x) ln ls) (seq O n)) *)
 rewrite map_map with (f := (fun x : nat => proj (S n) 0 (S x))).
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 apply map_ext2; intros.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
 simpl.
(* Goal: @eq (list bool) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) *)
 rewrite in_seq_iff in H.
(* Goal: @eq (list bool) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) (if match n with | O => false | S m' => Nat.leb a m' end then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a n) ls (@nil bool)) *)
 destruct n; simpl in *.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 rewrite <- minus_n_O; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 trivial.
Qed.

(** * Time complexity

  We consider an obvious implementation of the language [BC] on a stack machine,
  as described in Section 3.4.2 of Bellantoni's PhD thesis.

  - The polynomial [polytime n e] is an upper for the execution time.

  - [sem_cost e vnl vsl] differs from above [sem e vnl vsl] by also computing the running time.
*)

Section TIME.

  Variable ptime_zero_cost ptime_succ_cost ptime_pred_cost ptime_cond_cost: nat.
  Variable ptime_proj_cost : nat -> nat -> nat -> nat.

  Fixpoint sem_cost_rec (sem_g sem_h0 sem_h1:list bs->list bs->bs*nat)(v:bs)(vnl vsl:list bs) :
    bs * nat :=
    match v with
      | nil => sem_g vnl vsl
      | b::v' =>
        if b
          then
            let sem_cost := sem_cost_rec sem_g sem_h0 sem_h1 v' vnl vsl in
              let sem_cost_h := sem_h1 (v'::vnl) (fst sem_cost :: vsl) in
                (fst sem_cost_h, snd sem_cost + snd sem_cost_h)
          else
            let sem_cost := sem_cost_rec sem_g sem_h0 sem_h1 v' vnl vsl in
              let sem_cost_h := sem_h0 (v'::vnl) (fst sem_cost :: vsl) in
                (fst sem_cost_h, snd sem_cost + snd sem_cost_h)
    end.

Fixpoint sem_cost (e:BC)(vnl vsl:list bs) : bs*nat :=
 match e with
 | zero => (nil, ptime_zero_cost)
 | proj n s j => (
   if leb (S j) n then
     nth j vnl nil
     else nth (j-n) vsl nil, ptime_proj_cost n s j
   )
 | succ b => (b :: hd nil vsl, ptime_succ_cost)
 | pred => (tail (hd nil vsl), ptime_pred_cost)
 | cond => (
     match vsl with
     | a :: b :: c :: d :: _ =>
       match a with
         | nil => b
         | true :: _ => c
         | false :: _ => d
       end
     | a :: b :: c :: _ =>
       match a with
         | nil => b
         | true :: _ => c
         | false :: _ => nil
       end
     | a :: b :: _ =>
       match a with
         | nil => b
         | _ => nil
       end
     | _ => nil
     end, ptime_cond_cost
   )
 | rec g h0 h1 =>
     sem_cost_rec (sem_cost g) (sem_cost h0) (sem_cost h1) (hd nil vnl) (tail vnl) vsl
 | comp _ _ h nl sl =>
   let sem_cost_nl := List.map (fun ne => sem_cost ne vnl nil) nl in
   let sem_cost_sl := List.map (fun se => sem_cost se vnl vsl) sl in
   let sem_nl := List.map (@fst _ _) sem_cost_nl in
   let sem_sl := List.map (@fst _ _) sem_cost_sl in
   let cost_nl := List.map (@snd _ _) sem_cost_nl in
   let cost_sl := List.map (@snd _ _) sem_cost_sl in
   let sem_cost_h := sem_cost h sem_nl sem_sl in
   (fst sem_cost_h, snd sem_cost_h + plusl cost_nl + plusl cost_sl)
 end.

Lemma sem_cost_correct :
 forall e n s,
 arities e = ok_arities n s ->
 forall vnl vsl,
 fst (sem_cost e vnl vsl) = sem e vnl vsl.
Proof.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
 refine (BC_ind_inf _ _ _ _ _ _ _ _); simpl; trivial; intros.
(* Goal: @eq (list (list bool)) (@cons (list bool) l (@firstn (list bool) s (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))))) (@cons (list bool) l (@app (list bool) (@firstn (list bool) s vsl) (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
 induction (hd nil vnl) as [ | [ | ] ]; simpl; trivial; congruence.
(* Goal: @eq (list bool) (@fst (list bool) nat (sem_cost h (@map (prod (list bool) nat) (list bool) (@fst (list bool) nat) (@map BC (prod (list bool) nat) (fun ne : BC => sem_cost ne vnl (@nil (list bool))) rl)) (@map (prod (list bool) nat) (list bool) (@fst (list bool) nat) (@map BC (prod (list bool) nat) (fun se : BC => sem_cost se vnl vsl) tl)))) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
 rewrite H2.
 do 2 rewrite map_map.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
 clear H.
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl (@nil (list bool)))) rl) (@map BC (list bool) (fun x : BC => @fst (list bool) nat (sem_cost x vnl vsl)) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) *)
 f_equal.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 induction rl; simpl; intros; trivial.
(* Goal: forall (r : BC) (_ : @In BC r tl) (vnl vsl : list (list bool)), @eq (list bool) (sem r vnl vsl) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
 rewrite H3, IHrl; auto with *.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
 induction tl; simpl; intros; trivial.
(* Goal: forall (r : BC) (_ : @In BC r tl) (vnl vsl : list (list bool)), @eq (list bool) (sem r vnl vsl) (sem r (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
 rewrite H4, IHtl; auto with *.
Qed.

  Variable ptime_zero ptime_succ ptime_pred ptime_cond: pol.
  Variable ptime_proj : nat -> nat -> nat -> pol.

  Hypothesis ptime_zero_spec : 
    snd (sem_cost zero nil nil) <= peval ptime_zero nil.

  Hypothesis ptime_zero_wf : pWF ptime_zero.

  Hypothesis ptime_zero_arity : parity ptime_zero = 0.

  Hypothesis ptime_succ_spec : forall b,
    snd (sem_cost (succ b) nil nil) <= peval ptime_succ nil.

  Hypothesis ptime_succ_wf : pWF ptime_succ.

  Hypothesis ptime_succ_arity : parity ptime_succ = 0.

  Hypothesis ptime_proj_spec : forall n s i l,
    length l = n ->
    snd (sem_cost (proj n s i) l nil) <= peval (ptime_proj n s i) (map (@length _) l).

  Hypothesis ptime_proj_wf : forall n s i, pWF (ptime_proj n s i).

  Hypothesis ptime_proj_arity : forall n s i, parity (ptime_proj n s i) = n.

  Hypothesis ptime_cond_spec : 
    snd (sem_cost cond nil nil) <= peval ptime_cond nil.

  Hypothesis ptime_cond_wf : pWF ptime_cond.

  Hypothesis ptime_cond_arity : parity ptime_cond = 0.

  Hypothesis ptime_pred_spec : 
    snd (sem_cost pred nil nil) <= peval ptime_pred nil.

  Hypothesis ptime_pred_wf : pWF ptime_pred.

  Hypothesis ptime_pred_arity : parity ptime_pred = 0.

Fixpoint poly_time n (e:BC) : pol :=
  match e with
    | zero => ptime_zero
    | succ _ => ptime_succ
    | pred => ptime_pred
    | cond  => ptime_cond
    | proj n s i => ptime_proj n s i
    | rec g h0 h1 => 
      pplus (pshift (poly_time (n - 1) g))
      (pmult (pproj n 0) (pplus (poly_time n h0) (poly_time n h1)))
    | comp n0 s h rl tl =>
      pplus (pplus (pcst n0 0) (pcomp (poly_time (length rl) h) (map (poly_BC n0) rl)))
      (pplus (pplusl (map (poly_time n0) rl)) (pplusl (map (poly_time n0) tl)))
  end.
 
Lemma poly_time_WF : forall e n s, arities e = ok_arities n s -> pWF (poly_time n e).
Proof.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 refine (BC_ind_inf _ _ _ _ _ _ _ _); simpl; trivial; intros; try pWF; auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 rewrite <- minus_n_O; auto.
(* Goal: pWF x *)
 apply in_map_iff in H5.
(* Goal: pWF x *)
(* Goal: pWF x *)
(* Goal: pWF x *)
 destruct H5 as [e2 [H5 H7] ]; subst.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 eapply pWF_poly_BC; eauto.
(* Goal: pWF x *)
 apply in_map_iff in H5.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 destruct H5 as [e2 [H5 H7] ]; subst; auto.
(* Goal: pWF x *)
 apply in_map_iff in H5.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
 destruct H5 as [e2 [H5 H7] ]; subst; auto.
Qed.

Lemma arity_poly_time : forall e n s,
  arities e = ok_arities n s ->
  parity (poly_time n e) = n.
Proof.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  apply BC_ind_inf; simpl; intros; auto.
(* Goal: @eq nat match match Init.Nat.max (@fst nat (list mon) (poly_time (S n) h0)) (@fst nat (list mon) (poly_time (S n) h1)) with | O => S n | S m' => S (Init.Nat.max n m') end with | O => S (@fst nat (list mon) (poly_time (Init.Nat.sub n O) g)) | S m' => S (Init.Nat.max (@fst nat (list mon) (poly_time (Init.Nat.sub n O) g)) m') end (S n) *)
(* Goal: @eq nat (Init.Nat.max (Init.Nat.max n (maxl (@map (prod nat (list mon)) nat (@fst nat (list mon)) (@map BC pol (poly_BC n) rl)))) (Init.Nat.max (@fst nat (list mon) (pplusl (@map BC pol (poly_time n) rl))) (@fst nat (list mon) (pplusl (@map BC pol (poly_time n) tl))))) n *)
  rewrite H3, H4, <- minus_n_O, H2.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  rewrite !Nat.max_idempotent; trivial.
(* Goal: @eq nat (Init.Nat.max (Init.Nat.max n (maxl (@map (prod nat (list mon)) nat (@fst nat (list mon)) (@map BC pol (poly_BC n) rl)))) (Init.Nat.max (@fst nat (list mon) (pplusl (@map BC pol (poly_time n) rl))) (@fst nat (list mon) (pplusl (@map BC pol (poly_time n) tl))))) n *)
  rewrite !parity_pplusl, !map_map.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  rewrite max_l; auto.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  rewrite max_l; auto.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  apply maxl_map; intros.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  eapply arity_poly_BC; eauto.
(* Goal: le (Init.Nat.max (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) rl)) (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl))) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  apply Nat.max_lub.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  apply maxl_bound_in; intros.
(* Goal: le e' (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  rewrite in_map_iff in H5.
(* Goal: le e' (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  destruct H5 as [p [Hp1 Hp2]].
(* Goal: le e' (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  rewrite <- Hp1.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
  rewrite H3; trivial.
(* Goal: le n (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  apply Nat.le_max_l.
(* Goal: le (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_time n x)) tl)) (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  apply le_trans with n.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
  apply maxl_map; intros.  
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
  apply H4; auto.
(* Goal: le n (Init.Nat.max n (maxl (@map BC nat (fun x : BC => @fst nat (list mon) (poly_BC n x)) rl))) *)
  apply Nat.le_max_l.
Qed.

Lemma sem_cost_bounded : forall e n s,
 arities e = ok_arities n s ->
 (forall vnl vsl,
   length vnl = n -> 
   length vsl = s -> 
   snd (sem_cost e vnl vsl) <=
   peval (poly_time n e) (List.map (@length _) vnl)).
Proof.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
refine (BC_ind_inf _ _ _ _ _ _ _ _); simpl; intros; trivial; try omega.

rewrite (@length_nil _ _ H); apply ptime_zero_spec.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply (ptime_proj_spec n s i vnl); trivial.
rewrite (@length_nil _ _ H); apply (ptime_succ_spec b).
rewrite (@length_nil _ _ H); apply ptime_pred_spec.
rewrite (@length_nil _ _ H); apply ptime_cond_spec.

rewrite !pplus_correct, pshift_correct.
rewrite pmult_correct, pplus_correct, pproj_correct.
(* Goal: @eq (list bool) (@nth (list bool) (Init.Nat.sub i O) vsl (@nil bool)) (@nth (list bool) (Init.Nat.sub i O) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (if Nat.leb i n then @nth (list bool) i vnl (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) vsl (@nil bool)) (if Nat.leb i n then @nth (list bool) i (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool))) (@nil bool) else @nth (list bool) (Init.Nat.sub i (S n)) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool))) (@nil bool)) *)
(* Goal: @eq (list bool) (@cons bool b (@hd (list bool) (@nil bool) vsl)) (@cons bool b (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) (@tl bool (@hd (list bool) (@nil bool) vsl)) (@tl bool (@hd (list bool) (@nil bool) (@app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S O | S l => O end (@nil bool))))) *)
(* Goal: @eq (list bool) match vsl with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end match @app (list bool) vsl (@repeat (list bool) match @length (list bool) vsl with | O => S (S (S (S O))) | S (O as l) => S (S (S O)) | S (S (O as l0) as l) => S (S O) | S (S (S (O as l1) as l0) as l) => S O | S (S (S (S l2 as l1) as l0) as l) => O end (@nil bool)) with | nil => @nil bool | cons a (nil as l) => @nil bool | cons a (cons b (nil as l0) as l) => match a with | nil => b | cons b0 l1 => @nil bool end | cons a (cons b (cons c (nil as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l2 => c | cons (false as b0) l2 => @nil bool end | cons a (cons b (cons c (cons d l2 as l1) as l0) as l) => match a with | nil => b | cons (true as b0) l3 => c | cons (false as b0) l3 => d end end *)
(* Goal: @eq (list bool) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) vnl) (@tl (list bool) vnl) vsl) (sem_rec (sem g) (sem h0) (sem h1) (@hd (list bool) (@nil bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@tl (list bool) (@app (list bool) vnl (@repeat (list bool) match @length (list bool) vnl with | O => S n | S l => Init.Nat.sub n l end (@nil bool)))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) *)
(* Goal: @eq (list bool) (sem h (@map BC (list bool) (fun ne : BC => sem ne vnl (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se vnl vsl) tl)) (sem h (@map BC (list bool) (fun ne : BC => sem ne (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@nil (list bool))) rl) (@map BC (list bool) (fun se : BC => sem se (@app (list bool) vnl (@repeat (list bool) (Init.Nat.sub n (@length (list bool) vnl)) (@nil bool))) (@app (list bool) vsl (@repeat (list bool) (Init.Nat.sub s (@length (list bool) vsl)) (@nil bool)))) tl)) *)
rewrite <- minus_n_O.
destruct vnl as [ | x vnl]; simpl in *;[ discriminate | ].
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
induction x; simpl.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
rewrite <- plus_n_O; auto.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
destruct a; simpl.
eapply le_trans.
apply plus_le_compat.
apply IHx.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
apply H4; simpl; omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
rewrite <- !plus_assoc; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply plus_le_compat; trivial.
match goal with 
  [ |- ?a + ?b <= ?c + (?d + ?e) ] => apply le_trans with (e + d);[ | omega ]
end.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply plus_le_compat; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply mult_le_compat; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply plus_le_compat; trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
apply peval_monotonic; intros; simpl.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
destruct i; simpl; try omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
apply peval_monotonic; intros; simpl.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
destruct i; simpl; try omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
apply peval_monotonic; intros; simpl.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
destruct i; simpl; try omega.
eapply le_trans.
apply plus_le_compat.
apply IHx.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
apply H3; simpl; omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
rewrite <- !plus_assoc; simpl.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply plus_le_compat; trivial.
match goal with 
  [ |- ?a + ?b <= ?c + (?d + ?e) ] => apply le_trans with (e + c);[ | omega]
end.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply plus_le_compat; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply mult_le_compat; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply plus_le_compat; trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
apply peval_monotonic; intros; simpl.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
destruct i; simpl; try omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
apply peval_monotonic; intros; simpl.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
destruct i; simpl; try omega.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
apply peval_monotonic; intros; simpl.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
destruct i; simpl; try omega.

(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
rewrite !pplus_correct, pcst_correct, pcomp_correct, !pplusl_correct; simpl.
rewrite !plus_assoc.
apply plus_le_compat.
apply plus_le_compat.
eapply le_trans.
(* Goal: P n s (proj n s n2) *)
(* Goal: P n s (succ b) *)
(* Goal: P n s pred *)
(* Goal: P n s cond *)
(* Goal: P n s (rec e1 e2 e3) *)
(* Goal: P n s (comp n0 n1 e l l0) *)
apply H2.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
rewrite !map_length; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
rewrite !map_length; trivial.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
rewrite !map_map; simpl.
apply peval_monotonic.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
destruct (lt_dec i (length rl)).
erewrite map_nth2.
eapply le_trans.
erewrite sem_cost_correct.
eapply polymax_bounding.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply H0; apply nth_In; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
apply H0; apply nth_In; trivial.
erewrite map_nth2.
(* Goal: @eq (list bool) (sem (proj (S n) O (S a)) (@cons (list bool) d ln) ls) (sem (proj n O a) ln ls) *)
simpl.
instantiate (1 := zero).
instantiate (1 := zero).
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
omega.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
simpl; rewrite pcst_correct; trivial.
(* Goal: @eq (list bool) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) (if Nat.leb a n then @nth (list bool) a ln (@nil bool) else @nth (list bool) (Init.Nat.sub a (S n)) ls (@nil bool)) *)
simpl; trivial.
(* Goal: @eq nat n0 (Init.Nat.sub a (S (S n))) *)
rewrite !nth_overflow; trivial; rewrite map_length; omega.
rewrite !map_map.
apply plusl_compat.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
apply H3; auto.
rewrite !map_map.
apply plusl_compat.
(* Goal: forall (n : nat) (ln ls : list (list bool)) (d : list bool), @eq (list (list bool)) (@map BC (list bool) (fun x : BC => sem x (@cons (list bool) d ln) ls) (@map nat BC (proj (S n) O) (seq (S O) n))) (@map BC (list bool) (fun x : BC => sem x ln ls) (@map nat BC (proj n O) (seq O n))) *)
intros.
(* Goal: @eq (list bool) (sem (zero_e n1 s1) vnl vsl) (@nil bool) *)
apply H4; auto.
Qed.

End TIME.
