(**************************************************************)
(*   Copyright Dominique Larchey-Wendling [*]                 *)
(*                                                            *)
(*                             [*] Affiliation LORIA -- CNRS  *)
(**************************************************************)
(*      This file is distributed under the terms of the       *)
(*         CeCILL v2 FREE SOFTWARE LICENSE AGREEMENT          *)
(**************************************************************)

Require Import List Arith Omega Bool.

Require Import utils pos vec. 
Require Import subcode sss.
Require Import list_bool tiles_solvable bsm_defs.

Set Implicit Arguments.

Tactic Notation "rew" "length" := autorewrite with length_db.

Local Notation "e #> x" := (vec_pos e x).
Local Notation "e [ v / x ]" := (vec_change e x v).

Local Notation "P // s -[ k ]-> t" := (sss_steps (@bsm_sss _) P k s t).
Local Notation "P // s ->> t" := (sss_compute (@bsm_sss _) P s t).

Section Binary_Stack_Machines.

  Variable (n : nat).

  Ltac dest x y := destruct (pos_eq_dec x y) as [ | ]; [ subst x | ]; rew vec.

  Section empty_stack.

    Variable (x : pos n) (i : nat).
    
    (* Code for emptying stack x *)

    Definition empty_stack := POP x i (3+i) :: PUSH x Zero :: POP x i i :: nil.

    Fact empty_stack_length : length empty_stack = 3.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. auto. Qed.

    Fact empty_stack_spec v : (i,empty_stack) // (i,v) ->> (3+i,v[nil/x]).
    Proof.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i empty_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      set (l := v#>x).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i empty_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      generalize (eq_refl l).
(* Goal: forall _ : @eq (list bool) l l, @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i empty_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      unfold l at 2.
(* Goal: forall _ : @eq (list bool) l (@vec_pos (list bool) n v x), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i empty_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      generalize l v; clear l v.
(* Goal: forall (l : list bool) (v : vec (list bool) n) (_ : @eq (list bool) l (@vec_pos (list bool) n v x)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i empty_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      unfold empty_stack.
(* Goal: forall (l : list bool) (v : vec (list bool) n) (_ : @eq (list bool) l (@vec_pos (list bool) n v x)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      induction l as [ | [] l IHl ]; intros v Hv.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      bsm sss POP empty with x i (3+i).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (vec (list bool) n) v (@vec_change (list bool) n v x (@nil bool)) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      apply vec_pos_ext; intros p; dest x p.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      bsm sss POP 1 with x i (3+i) l.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with x Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S O) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x)))) (@pair nat (vec (list bool) n) q w) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 0 with x i i l; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      clear Hv.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      specialize (IHl (v[l/x])).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      spec in IHl.     
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      rew vec.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      revert IHl; rew vec.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      bsm sss POP 0 with x i (3+i) l.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      clear Hv.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      specialize (IHl (v[l/x])).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x i (Init.Nat.add (S (S (S O))) i)) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) i) (@vec_change (list bool) n v x (@nil bool))) *)
      spec in IHl.     
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      rew vec.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      revert IHl; rew vec.
    Qed.

  End empty_stack.

  Section move_rev.

    Variable (x y : pos n) (Hxy : x <> y) (i : nat).

    Let y' := y.
    
    (* Code that transfers stack x to y, reversing x in the interval *)

    Definition move_rev_stack := 
      (*    i *)   POP x (4+i) (7+i) ::
      (*  1+i *)   PUSH y One  :: PUSH y' Zero :: POP y' i i ::
      (*  4+i *)   PUSH y Zero :: PUSH x  Zero :: POP x i i ::
      (*  7+i *)   nil.

    Fact length_move_rev_stack : length move_rev_stack = 7.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. auto. Qed. 

    Fact move_rev_stack_spec l v w :
              v#>x = l
           -> w = v[nil/x][(rev l++v#>y)/y] 
           -> (i,move_rev_stack) // (i,v) ->> (7+i,w).
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v x) l) (_ : @eq (vec (list bool) n) w (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool l) (@vec_pos (list bool) n v y)))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i move_rev_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i) w) *)
      revert v w; induction l as [ | [] l IHl ]; intros v w Hv Hw; subst w; unfold move_rev_stack.
      * bsm sss POP empty with x (4+i) (7+i).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        bsm sss stop.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v x (@list_repeat bool false (S k))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y)))) x (@cons bool false (@nil bool))) y (@vec_pos (list bool) n v y)) x (@app bool (@list_repeat bool false k) (@cons bool false (@nil bool)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
        apply vec_pos_ext; intros z; dest z y; dest z x.
      * bsm sss POP 1 with x (4+i) (7+i) l.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n y true) (@cons (bsm_instr n) (@bsm_push n z true) (@cons (bsm_instr n) (@bsm_push n y' false) (@cons (bsm_instr n) (@bsm_pop n y' i i) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_push n z false) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) i) (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v z)))) *)
        bsm sss PUSH with y One.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n y true) (@cons (bsm_instr n) (@bsm_push n z true) (@cons (bsm_instr n) (@bsm_push n y' false) (@cons (bsm_instr n) (@bsm_pop n y' i i) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_push n z false) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S O) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n v x l) y))) z (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n v x l) y))) z)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v z)))) *)
        bsm sss PUSH with y' Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        bsm sss POP 0 with y' i i (One::v#>y); unfold y'; rew vec.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        apply IHl; rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) c lc) h (@app bool thh (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) h))) l (@app bool tll (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) l))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool (@app bool thh th) (@vec_pos (list bool) n v h))) l (@app bool (@app bool tll tl) (@vec_pos (list bool) n v l))) *)
        apply vec_pos_ext; intros z.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool false l)) (@vec_pos (list bool) n v y))) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) y (@app bool (@rev bool l) (@cons bool false (@vec_pos (list bool) n v y)))) z) *)
        dest z y; simpl; solve list eq.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
        dest z x.
      * bsm sss POP 0 with x (4+i) (7+i) l.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
        bsm sss PUSH with y Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
        bsm sss PUSH with x Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S O) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x)))) (@pair nat (vec (list bool) n) q w) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
        bsm sss POP 0 with x i i l; rew vec.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        apply IHl; rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) c lc) h (@app bool thh (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) h))) l (@app bool tll (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) l))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool (@app bool thh th) (@vec_pos (list bool) n v h))) l (@app bool (@app bool tll tl) (@vec_pos (list bool) n v l))) *)
        apply vec_pos_ext; intros z.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool false l)) (@vec_pos (list bool) n v y))) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) y (@app bool (@rev bool l) (@cons bool false (@vec_pos (list bool) n v y)))) z) *)
        dest z y; simpl; solve list eq.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
        dest z x.
    Qed.

  End move_rev.

  Section copy_rev_stack.

    Variable (x y z : pos n) (Hxy : x <> y) (Hxz : x <> z) (Hyz : y <> z) (i : nat).

    Let y' := y.
    
    (* Code that transfers x to both y and z, reversing x in the interval *)

    Definition copy_rev_stack := 
      (*    i *)   POP x (5+i) (9+i) ::
      (*  1+i *)   PUSH y One  :: PUSH z One  :: PUSH y' Zero :: POP y' i i ::
      (*  5+i *)   PUSH y Zero :: PUSH z Zero :: PUSH x Zero :: POP x i i ::
      (*  9+i *)   nil.

    Fact length_copy_rev_stack : length copy_rev_stack = 9.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. auto. Qed.

    Fact copy_rev_stack_spec l v w :
              v#>x = l
           -> w = v[nil/x][(rev l++v#>y)/y][(rev l++v#>z)/z]
           -> (i,copy_rev_stack) // (i,v) ->> (9+i,w).
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v x) l) (_ : @eq (vec (list bool) n) w (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool l) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool l) (@vec_pos (list bool) n v z)))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i copy_rev_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i) w) *)
      revert v w; induction l as [ | [] l IHl ]; intros v w Hv Hw; subst w; unfold copy_rev_stack.
      * bsm sss POP empty with x (5+i) (9+i).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        bsm sss stop.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        f_equal.
(* Goal: @eq (vec (list bool) n) v (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@nil bool)) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool (@nil bool)) (@vec_pos (list bool) n v z))) *)
        apply vec_pos_ext; intros k; dest k z; dest k y; dest k x.
      * bsm sss POP 1 with x (5+i) (9+i) l.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n y true) (@cons (bsm_instr n) (@bsm_push n z true) (@cons (bsm_instr n) (@bsm_push n y' false) (@cons (bsm_instr n) (@bsm_pop n y' i i) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_push n z false) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) i) (@vec_change (list bool) n v x l)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v z)))) *)
        bsm sss PUSH with y One.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n y true) (@cons (bsm_instr n) (@bsm_push n z true) (@cons (bsm_instr n) (@bsm_push n y' false) (@cons (bsm_instr n) (@bsm_pop n y' i i) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_push n z false) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) i)) (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n v x l) y)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v z)))) *)
        bsm sss PUSH with z One.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n y true) (@cons (bsm_instr n) (@bsm_push n z true) (@cons (bsm_instr n) (@bsm_push n y' false) (@cons (bsm_instr n) (@bsm_pop n y' i i) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_push n z false) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S O) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n v x l) y))) z (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n v x l) y))) z)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool (@cons bool true l)) (@vec_pos (list bool) n v z)))) *)
        bsm sss PUSH with y' Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        bsm sss POP 0 with y' i i (One::v#>y); unfold y'; rew vec.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        apply IHl; rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@nil bool)) x (@app bool (@rev bool (@rev bool l)) (@nil bool))) y (@app bool (@rev bool (@rev bool l)) (@vec_pos (list bool) n v y))) *)
        apply vec_pos_ext; intros k.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y))) k) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@nil bool)) x (@app bool (@rev bool (@rev bool l)) (@nil bool))) y (@app bool (@rev bool (@rev bool l)) (@vec_pos (list bool) n v y))) k) *)
        dest k z; simpl; solve list eq.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool l) (@cons bool false (@vec_pos (list bool) n v y)))) k) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) z (@cons bool false (@vec_pos (list bool) n v z))) x (@nil bool)) y (@app bool (@rev bool l) (@cons bool false (@vec_pos (list bool) n v y)))) k) *)
        dest k y; dest k x.
      * bsm sss POP 0 with x (5+i) (9+i) l.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
        bsm sss PUSH with y Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n y true) (@cons (bsm_instr n) (@bsm_push n z true) (@cons (bsm_instr n) (@bsm_push n y' false) (@cons (bsm_instr n) (@bsm_pop n y' i i) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_push n z false) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@nil (bsm_instr n)))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S (S (S O))))) i)) (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v x l) y)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool (@cons bool false l)) (@vec_pos (list bool) n v y))) z (@app bool (@rev bool (@cons bool false l)) (@vec_pos (list bool) n v z)))) *)
        bsm sss PUSH with z Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
        bsm sss PUSH with x Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S O) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x)))) (@pair nat (vec (list bool) n) q w) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
        bsm sss POP 0 with x i i l; rew vec.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        apply IHl; rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@nil bool)) x (@app bool (@rev bool (@rev bool l)) (@nil bool))) y (@app bool (@rev bool (@rev bool l)) (@vec_pos (list bool) n v y))) *)
        apply vec_pos_ext; intros k.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y))) k) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@nil bool)) x (@app bool (@rev bool (@rev bool l)) (@nil bool))) y (@app bool (@rev bool (@rev bool l)) (@vec_pos (list bool) n v y))) k) *)
        dest k z; simpl; solve list eq.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@rev bool l) (@cons bool false (@vec_pos (list bool) n v y)))) k) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) z (@cons bool false (@vec_pos (list bool) n v z))) x (@nil bool)) y (@app bool (@rev bool l) (@cons bool false (@vec_pos (list bool) n v y)))) k) *)
        dest k y; dest k x.
    Qed.

  End copy_rev_stack.

  Hint Rewrite empty_stack_length length_move_rev_stack length_copy_rev_stack : length_db.
  
  Section copy_stack.

    Variable (x y z : pos n) (Hxy : x <> y) (Hxz : x <> z) (Hyz : y <> z) (i : nat).
    
    (* Code that copies x into y, stack z must be an empty spare stack *)

    Definition copy_stack := move_rev_stack x z i ++ copy_rev_stack z x y (7+i).

    Fact copy_stack_length : length copy_stack = 16.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. auto. Qed.

    Fact copy_stack_spec l v w :
              v#>x = l
           -> v#>z = nil
           -> w = v[(l++v#>y)/y]
           -> (i,copy_stack) // (i,v) ->> (16+i,w).
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v x) l) (_ : @eq (list bool) (@vec_pos (list bool) n v z) (@nil bool)) (_ : @eq (vec (list bool) n) w (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y)))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i copy_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) w) *)
      intros H1 H2 H3; subst w.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i copy_stack) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y)))) *)
      unfold copy_stack.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (move_rev_stack x z i) (copy_rev_stack z x y (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y)))) *)
      apply sss_compute_trans with (st2 := (7+i,v[nil/x][(rev l)/z])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      * apply subcode_sss_compute with (P := (i,move_rev_stack x z i)); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply move_rev_stack_spec with l; auto.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@rev bool l)) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@app bool (@rev bool l) (@vec_pos (list bool) n v z))) *)
        rew vec; rewrite H2; solve list eq.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      * apply subcode_sss_compute with (P := (7+i,copy_rev_stack z x y (7+i))); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        apply copy_rev_stack_spec with (rev l); rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@nil bool)) x (@app bool (@rev bool (@rev bool l)) (@nil bool))) y (@app bool (@rev bool (@rev bool l)) (@vec_pos (list bool) n v y))) *)
        apply vec_pos_ext; intros k.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v y (@app bool l (@vec_pos (list bool) n v y))) k) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) z (@nil bool)) x (@app bool (@rev bool (@rev bool l)) (@nil bool))) y (@app bool (@rev bool (@rev bool l)) (@vec_pos (list bool) n v y))) k) *)
        dest k z; simpl; solve list eq.
        dest k y; [ | dest k x ];
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        rewrite rev_involutive; auto.
    Qed.

  End copy_stack.

  Hint Rewrite copy_stack_length : length_db.

  Section compare_stacks.

    Variables (x y : pos n) (Hxy : x <> y) (i p q : nat).

    Let x' := x.
    
    (* Code that compares two stacks x and y:
          - ends at p if the stacks x and y are identical
          - ends at q otherwise
       The status of x and y is unspecified after the
       execution but the stacks other than x and y are
       unmodified *)

    Definition compare_stacks :=
      (*   i    *)  POP x (4+i) (7+i) ::
      (* 1+i    *)  POP y q q ::
      (* 2+i    *)  PUSH x Zero :: POP x i i ::
      (* 4+i    *)  POP y i q ::
      (* 5+i    *)  PUSH y Zero :: POP y q i ::
      (* 7+i    *)  POP y q p ::
      (* 8+i    *)  PUSH x' Zero :: POP x' q q :: nil.

    Fact compare_stacks_length : length compare_stacks = 10.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. auto. Qed.

    Let cs_spec_rec l : forall m v, v#>x = l 
                                 -> v#>y = m 
                                 -> exists w, (forall z, z <> x -> z <> y -> v#>z = w#>z)
                                 /\ (l =  m -> (i,compare_stacks) // (i,v) ->> (p,w))
                                 /\ (l <> m -> (i,compare_stacks) // (i,v) ->> (q,w)).
    Proof.
(* Goal: forall (m : list bool) (v : vec (list bool) n) (_ : @eq (list bool) (@vec_pos (list bool) n v x) l) (_ : @eq (list bool) (@vec_pos (list bool) n v y) m), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) l m, @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i compare_stacks) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) l m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i compare_stacks) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      induction l as [ | [] l IHl ]; intros [ | [] m ] v Hx Hy; unfold compare_stacks.

      (* l = nil, m = nil *)
   
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      exists v; split; auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      split; [ intros _ | intros [] ]; auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP empty with x (4+i) (7+i).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i) v) (@pair nat (vec (list bool) n) p v) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP empty with y q p.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.

      (* l = nil, m = One::_ *)
      
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      exists (v[m/y]); split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros; rew vec.
(* Goal: and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      split; [ discriminate | intros _ ].
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP empty with x (4+i) (7+i).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i) v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 1 with y q p m.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@vec_change (list bool) n v y m)) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss PUSH with x' Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n v y m) x' (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v y m) x')))) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 0 with x' q q nil.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      rew vec; f_equal; auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      unfold x'; rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v y m) x (@nil bool)) (@vec_change (list bool) n v y m) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      apply vec_pos_ext; intros z; dest x z.

      (* l = nil, m = Zero::_ *)

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@nil bool) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@nil bool) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      exists (v[m/y]); split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros; rew vec.
(* Goal: and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      split; [ discriminate | intros _ ].
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP empty with x (4+i) (7+i).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i) v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 0 with y q p m.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.

      (* l = One::_, m = nil *)

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      exists (v[l/x]); split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros; rew vec.
(* Goal: and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      split; [ discriminate | intros _ ].
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 1 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP empty with y q q; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.

      (* l = One::l', m = One::m' *)

(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      destruct (IHl m (v[l/x][m/y])) as (w & H1 & H2 & H3); rew vec.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
      exists w; split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros z G1 G2; specialize (H1 _ G1 G2); rewrite <- H1; rew vec.
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
      split. 

(* Goal: forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w) *)
(* Goal: forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      intros E1; inversion E1 as [ E ]; clear E1.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w) *)
(* Goal: forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      specialize (H2 E).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 1 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 1 with y q q m; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with x Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S O) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x)))) (@pair nat (vec (list bool) n) q w) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 0 with x i i l; rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      eq goal H2; do 2 f_equal.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
      apply vec_pos_ext; intros z; dest z x.

(* Goal: forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      intros E1.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      spec in H3.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      contradict E1; subst; auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 1 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 1 with y q q m; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with x Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) (Init.Nat.add (S O) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m) x)))) (@pair nat (vec (list bool) n) q w) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool true l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool true l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 0 with x i i l; rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      eq goal H3; do 2 f_equal.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
      apply vec_pos_ext; intros z; dest z x.

      (* l = One::l', m = Zero::m' *)

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      exists (v[l/x][m/y]).
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
      split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros; rew vec.
(* Goal: and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      split; [ discriminate | intros _ ].
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      bsm sss POP 1 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with y q q m; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.

      (* l = Zero::l', m = nil *)

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@nil bool), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      exists (v[l/x]).
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
      split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros; rew vec.
(* Goal: and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      split; [ discriminate | intros _ ].
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      bsm sss POP 0 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP empty with y i q; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.

      (* l = Zero::l', m = nil *)

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      exists (v[l/x][m/y]).
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
      split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros; rew vec.
(* Goal: and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool true m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool true m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n (@vec_change (list bool) n v x l) y m))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (and (forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)))) *)
      split; [ discriminate | intros _ ].
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      bsm sss POP 0 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 1 with y i q m; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with y Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with y q i m; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.

      (* l = Zero::l', m = Zero::m' *)

(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      destruct (IHl m (v[l/x][m/y])) as (w & H1 & H2 & H3); rew vec.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
      exists w; split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros z G1 G2; specialize (H1 _ G1 G2); rewrite <- H1; rew vec.
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
      split. 

(* Goal: forall _ : @eq (list bool) (@cons bool false l) (@cons bool false m), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w) *)
(* Goal: forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      intros E1; inversion E1 as [ E ]; clear E1.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w) *)
(* Goal: forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      specialize (H2 E).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      bsm sss POP 0 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with y i q m; rew vec.

(* Goal: forall _ : not (@eq (list bool) (@cons bool false l) (@cons bool false m)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      intros E1.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      spec in H3.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      contradict E1; subst; auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n x (Init.Nat.add (S (S (S (S O)))) i) (Init.Nat.add (S (S (S (S (S (S (S O))))))) i)) (@cons (bsm_instr n) (@bsm_pop n y q q) (@cons (bsm_instr n) (@bsm_push n x false) (@cons (bsm_instr n) (@bsm_pop n x i i) (@cons (bsm_instr n) (@bsm_pop n y i q) (@cons (bsm_instr n) (@bsm_push n y false) (@cons (bsm_instr n) (@bsm_pop n y q i) (@cons (bsm_instr n) (@bsm_pop n y q p) (@cons (bsm_instr n) (@bsm_push n x' false) (@cons (bsm_instr n) (@bsm_pop n x' q q) (@nil (bsm_instr n))))))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
      bsm sss POP 0 with x (4+i) (7+i) l.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with y i q m; rew vec.
    Qed.

    Fact compare_stack_eq_spec v : 
            v#>x = v#>y 
         ->   exists w, (i,compare_stacks) // (i,v) ->> (p,w) 
           /\ forall z, z <> x -> z <> y -> v#>z = w#>z.
    Proof.
(* Goal: not (@eq (list nat) ln (@nil nat)) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
      intros E.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i compare_stacks) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      destruct (cs_spec_rec v eq_refl eq_refl) as (w & H1 & H2 & H3).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      exists w; split; auto.
    Qed.

    Fact compare_stack_neq_spec v : 
            v#>x <> v#>y 
         ->   exists w, (i,compare_stacks) // (i,v) ->> (q,w) 
           /\ forall z, z <> x -> z <> y -> v#>z = w#>z.
    Proof.
(* Goal: not (@eq (list nat) ln (@nil nat)) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
      intros E.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i compare_stacks) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      destruct (cs_spec_rec v eq_refl eq_refl) as (w & H1 & H2 & H3).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      exists w; split; auto.
    Qed.

    Theorem compare_stack_spec v : exists j w, (i,compare_stacks) // (i,v) ->> (j,w) 
                                         /\ forall z, z <> x -> z <> y -> v#>z = w#>z
                                         /\ (v#>x = v#>y /\ j = p \/ v#>x <> v#>y /\ j = q).
    Proof.
(* Goal: @ex nat (fun j : nat => @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i compare_stacks) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) j w)) (forall (z : pos n) (_ : not (@eq (pos n) z x)) (_ : not (@eq (pos n) z y)), and (@eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z)) (or (and (@eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n v y)) (@eq nat j p)) (and (not (@eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n v y))) (@eq nat j q)))))) *)
      destruct (list_bool_dec (v#>x) (v#>y)) as [ H | H ].
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      + destruct compare_stack_eq_spec with (1 := H) as (w & H1 & H2); exists p, w; auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      + destruct compare_stack_neq_spec with (1 := H) as (w & H1 & H2); exists q, w; auto.
    Qed.

  End compare_stacks.

  Section half_tile.

    Variable (x : pos n).
    
    (* Code that pushes the reverse of a half tile on a stack *)

    Fixpoint half_tile (l : list bool) := 
      match l with
        | nil  => nil
        | b::l => PUSH x b :: half_tile l
      end.

    Fact half_tile_length l : length (half_tile l) = length l.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. induction l; simpl; f_equal; auto. Qed. 

    Fact half_tile_spec i l v : (i,half_tile l) // (i,v) ->> (length (half_tile l)+i,v[(rev l++v#>x)/x]).
    Proof.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (half_tile l)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile l)) i) (@vec_change (list bool) n v x (@app bool (@rev bool l) (@vec_pos (list bool) n v x)))) *)
      rewrite half_tile_length.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (half_tile l)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (@length bool l) i) (@vec_change (list bool) n v x (@app bool (@rev bool l) (@vec_pos (list bool) n v x)))) *)
      revert i v; induction l as [ | b l IHl ]; intros i v; simpl.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
      apply vec_pos_ext; intros z; dest z x.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n x b) (half_tile l))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (S (Init.Nat.add (@length bool l) i)) (@vec_change (list bool) n v x (@app bool (@app bool (@rev bool l) (@cons bool b (@nil bool))) (@vec_pos (list bool) n v x)))) *)
      bsm sss PUSH with x b.
      specialize (IHl (1+i) (v[(b::v#>x)/x])).
      apply subcode_sss_compute with (P := (1+i,half_tile l)).
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      eq goal IHl; do 2 f_equal.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      omega.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
      apply vec_pos_ext; intros z; dest z x.
(* Goal: @eq (list bool) (@app bool (@rev bool l) (@cons bool b (@vec_pos (list bool) n v x))) (@app bool (@app bool (@rev bool l) (@cons bool b (@nil bool))) (@vec_pos (list bool) n v x)) *)
      solve list eq.
    Qed.

  End half_tile.

  Hint Rewrite empty_stack_length compare_stacks_length half_tile_length : length_db.

  Section tile.

    Variable (x y : pos n) (Hxy : x <> y) (high low : list bool).
    
    (* Code that pushes a reversed tile on both stacks high and low *)
  
    Definition tile := half_tile x (rev high) ++ half_tile y (rev low).

    Fact tile_length : length tile = length high + length low.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. unfold tile; rew length; auto. Qed.

    Fact tile_spec i v st : st = (length tile+i,v[(high++v#>x)/x][(low++v#>y)/y]) 
                         -> (i,tile) // (i,v) ->> st.
    Proof.
(* Goal: forall _ : @eq (prod nat (vec (list bool) n)) st (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) tile) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool low (@vec_pos (list bool) n v y)))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i tile) (@pair nat (vec (list bool) n) i v) st *)
      intro; subst.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i tile) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) tile) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool low (@vec_pos (list bool) n v y)))) *)
      unfold tile.
      apply sss_compute_trans with (st2 := (length (half_tile x (rev high))+i,v[(high++v#>x)/x])).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool low (@vec_pos (list bool) n v y)))) *)
      rewrite <- (rev_involutive high) at 3.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool (@rev bool (@rev bool high)) (@vec_pos (list bool) n v x)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool low (@vec_pos (list bool) n v y)))) *)
      apply subcode_sss_compute with (P := (i,half_tile x (rev high))).
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) i (half_tile x (@rev bool high))) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (half_tile x (@rev bool high))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool (@rev bool (@rev bool high)) (@vec_pos (list bool) n v x)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool low (@vec_pos (list bool) n v y)))) *)
      subcode_tac.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (half_tile y (@rev bool low))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile y (@rev bool low))) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i)) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool (@rev bool (@rev bool low)) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y)))) *)
(* Goal: @eq nat (Init.Nat.add (@length (bsm_instr n) (half_tile y (@rev bool low))) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i)) (Init.Nat.add (@length (bsm_instr n) (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) i) *)
      apply half_tile_spec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool low (@vec_pos (list bool) n v y)))) *)
      rewrite <- (rev_involutive low) at 3.
      apply subcode_sss_compute with (P := (length (half_tile x (rev high))+i,half_tile y (rev low))).
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
      replace (length (half_tile x (rev high) ++ half_tile y (rev low)) + i)
      with    (length (half_tile y (rev low)) + (length (half_tile x (rev high)) + i)).
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      replace (v#>y) with (v[(high ++ v#>x)/x]#>y) by rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (half_tile y (@rev bool low))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i) (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x)))) (@pair nat (vec (list bool) n) (Init.Nat.add (@length (bsm_instr n) (half_tile y (@rev bool low))) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i)) (@vec_change (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y (@app bool (@rev bool (@rev bool low)) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@app bool high (@vec_pos (list bool) n v x))) y)))) *)
(* Goal: @eq nat (Init.Nat.add (@length (bsm_instr n) (half_tile y (@rev bool low))) (Init.Nat.add (@length (bsm_instr n) (half_tile x (@rev bool high))) i)) (Init.Nat.add (@length (bsm_instr n) (@app (bsm_instr n) (half_tile x (@rev bool high)) (half_tile y (@rev bool low)))) i) *)
      apply half_tile_spec.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      rew length; omega.
    Qed.

  End tile.

  Hint Rewrite tile_length : length_db.
  
  Section transfer_ones.

    Variable (x y : pos n) (Hxy : x <> y) (i p q : nat).
    
    (* Code that does the following:
         * if x is 111110++l where 1 occurs k times then
            - x becomes l
            - y becomes bbbbb++y where b occurs k times
         * if x is 11111 where 1 occurs k times then
            - x becomes nil
            - y becomes bbbbb++y where b occurs k times
     *)

    Definition transfer_ones b := POP x p q :: PUSH y b :: PUSH y Zero :: POP y i i :: nil.

    Fact transfer_ones_length b : length (transfer_ones b) = 4.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. auto. Qed.

    Fact transfer_ones_spec_1 b k l v st : v#>x = list_repeat One k ++ Zero :: l 
                                    -> st = (p,v[l/x][(list_repeat b k ++ v#>y)/y])
                                    -> (i,transfer_ones b) // (i,v) ->> st.
    Proof.
      intros H1 E; subst st.
      revert v H1.
      induction k as [ | k IHk ]; intros v; intros Hx; 
        simpl list_repeat; simpl app; unfold transfer_ones; simpl in Hx.

      bsm sss POP 0 with x p q l.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
      apply vec_pos_ext; intros z; dest z y.

      bsm sss POP 1 with x p q (list_repeat One k ++ Zero :: l).
      bsm sss PUSH with y b.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with y Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with y i i (b::v#>y); rew vec.
      specialize (IHk (v [(list_repeat One k ++ Zero :: l) / x] [(b :: v #> y) / y])).
      spec in IHk.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      eq goal IHk; do 2 f_equal.
      apply vec_pos_ext; intros z; dest z y.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
      2: dest z x. 
      change (b :: list_repeat b k ++ v#>y)
      with (list_repeat b (S k) ++ v#>y).
      replace (S k) with (k+1) by omega.
(* Goal: @eq (list bool) (@app bool (@rev bool l) (@cons bool b (@vec_pos (list bool) n v x))) (@app bool (@app bool (@rev bool l) (@cons bool b (@nil bool))) (@vec_pos (list bool) n v x)) *)
      rewrite list_repeat_plus; solve list eq.
    Qed.

    Fact transfer_ones_spec_2 b k v st : v#>x = list_repeat One k 
                                    -> st = (q,v[nil/x][(list_repeat b k ++ v#>y)/y])
                                    -> (i,transfer_ones b) // (i,v) ->> st.
    Proof.
      intros H1 E; subst st.
      revert v H1.
      induction k as [ | k IHk ]; intros v; intros Hx; 
        simpl list_repeat; simpl app; unfold transfer_ones; simpl in Hx.

      bsm sss POP empty with x p q.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v x (@list_repeat bool false (S k))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y)))) x (@cons bool false (@nil bool))) y (@vec_pos (list bool) n v y)) x (@app bool (@list_repeat bool false k) (@cons bool false (@nil bool)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      apply vec_pos_ext; intros z; dest z y; dest z x.

      bsm sss POP 1 with x p q (list_repeat One k).
      bsm sss PUSH with y b.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with y Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with y i i (b::v#>y); rew vec.
      specialize (IHk (v [(list_repeat One k) / x] [(b :: v #> y) / y])).
      spec in IHk.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      eq goal IHk; do 2 f_equal.
      apply vec_pos_ext; intros z; dest z y.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v x (@nil bool)) z) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@cons bool false (@vec_pos (list bool) n v y))) x (@nil bool)) z) *)
      2: dest z x. 
      change (b :: list_repeat b k ++ v#>y)
      with (list_repeat b (S k) ++ v#>y).
      replace (S k) with (k+1) by omega.
(* Goal: @eq (list bool) (@app bool (@rev bool l) (@cons bool b (@vec_pos (list bool) n v x))) (@app bool (@app bool (@rev bool l) (@cons bool b (@nil bool))) (@vec_pos (list bool) n v x)) *)
      rewrite list_repeat_plus; solve list eq.
    Qed.

  End transfer_ones.

  Hint Rewrite transfer_ones_length : length_db.

  Section increment.

    Variable (x y : pos n) (Hxy : x <> y).
    
    (* Code that increments the stack x by one ie.
       for l such that list_bool_succ x l, x becomes l
       
       y is a spare register which is (globally) unmodified
    *)

    Definition increment i := PUSH y Zero :: transfer_ones x y (1+i)   (5+i) (10+i) One  ++ 
                              PUSH x One  :: transfer_ones y x (6+i)  (15+i) (15+i) Zero ++
                              PUSH x Zero :: transfer_ones y x (11+i) (15+i) (15+i) Zero ++ 
                              nil.

    Fact increment_length i : length (increment i) = 15.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. unfold increment; rew length; auto. Qed.

    Fact increment_spec_1 i v k l : v#>x = list_repeat One k ++ Zero :: l
                               -> (i,increment i) // (i,v) ->> (15+i,v[(list_repeat Zero k ++ One :: l)/x]).
    Proof.
(* Goal: forall _ : @eq (list bool) (@vec_pos (list bool) n v x) (@list_repeat bool true k), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (increment i)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      intros Hx.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (increment i)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      unfold increment.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with y Zero.

      apply subcode_sss_compute_trans with (P := (1+i,transfer_ones x y (1+i) (5+i) (10+i) One))
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
                                           (st2 := (5+i,v[l/x][(list_repeat One k ++ Zero:: v#>y)/y])); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      apply transfer_ones_spec_1 with (k := k) (l := l); rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v x (@list_repeat bool false (S k))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y)))) x (@cons bool false (@nil bool))) y (@vec_pos (list bool) n v y)) x (@app bool (@list_repeat bool false k) (@cons bool false (@nil bool)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      apply vec_pos_ext; intros z; dest z y; dest z x.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x l) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@app bool (@list_repeat bool false k) (@cons bool true l)))) *)
      bsm sss PUSH with x One.
      apply subcode_sss_compute_trans with (P := (6+i,transfer_ones y x (6+i) (15+i) (15+i) Zero))
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
                                           (st2 := (15+i,v[(list_repeat Zero k++One::l)/x])); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      apply transfer_ones_spec_1 with (k := k) (l := v#>y); rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v x (@list_repeat bool false (S k))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y)))) x (@cons bool false (@nil bool))) y (@vec_pos (list bool) n v y)) x (@app bool (@list_repeat bool false k) (@cons bool false (@nil bool)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      apply vec_pos_ext; intros z; dest z y; dest z x.
 
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.
    Qed.

    Fact increment_spec_2 i v k : v#>x = list_repeat One k
                               -> (i,increment i) // (i,v) ->> (15+i,v[(list_repeat Zero (S k))/x]).
    Proof.
(* Goal: forall _ : @eq (list bool) (@vec_pos (list bool) n v x) (@list_repeat bool true k), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (increment i)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      intros Hx.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (increment i)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      unfold increment.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with y Zero.

      apply subcode_sss_compute_trans with (P := (1+i,transfer_ones x y (1+i) (5+i) (10+i) One))
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
                                           (st2 := (10+i,v[nil/x][(list_repeat One k ++ Zero:: v#>y)/y])); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      apply transfer_ones_spec_2 with (k := k); rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v x (@list_repeat bool false (S k))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y)))) x (@cons bool false (@nil bool))) y (@vec_pos (list bool) n v y)) x (@app bool (@list_repeat bool false k) (@cons bool false (@nil bool)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      apply vec_pos_ext; intros z; dest z y; dest z x.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      bsm sss PUSH with x Zero.
      apply subcode_sss_compute_trans with (P := (11+i,transfer_ones y x (11+i) (15+i) (15+i) Zero))
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
                                           (st2 := (15+i,v[(list_repeat Zero (S k))/x])); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      apply transfer_ones_spec_1 with (k := k) (l := v#>y); rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v x (@list_repeat bool false (S k))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v x (@nil bool)) y (@app bool (@list_repeat bool true k) (@cons bool false (@vec_pos (list bool) n v y)))) x (@cons bool false (@nil bool))) y (@vec_pos (list bool) n v y)) x (@app bool (@list_repeat bool false k) (@cons bool false (@nil bool)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_push n y false) (@app (bsm_instr n) (transfer_ones x y (Init.Nat.add (S O) i) (Init.Nat.add (S (S (S (S (S O))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S O)))))))))) i) true) (@cons (bsm_instr n) (@bsm_push n x true) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S O)))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@cons (bsm_instr n) (@bsm_push n x false) (@app (bsm_instr n) (transfer_ones y x (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S O))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) false) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x (@list_repeat bool false (S k)))) *)
      apply vec_pos_ext; intros z; dest z y; dest z x.
      replace (S k) with (k+1) by omega.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      rewrite list_repeat_plus; auto.
 
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.
    Qed.

    Fact increment_spec i v l m : 
           list_bool_succ l m 
        -> v#>x = l
        -> (i,increment i) // (i,v) ->> (15+i,v[m/x]).
    Proof.
(* Goal: forall (_ : list_bool_succ l m) (_ : @eq (list bool) (@vec_pos (list bool) n v x) l), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (increment i)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i) (@vec_change (list bool) n v x m)) *)
      revert l m; intros ? ? [ k l | k ] H.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply increment_spec_1; auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply increment_spec_2; auto.
    Qed.

  End increment.

  Hint Rewrite increment_length : length_db.

  Section full_decoder.
  
    Implicit Type (lt : list ((list bool) *  list bool)).

    Definition size_cards lt := fold_right (fun c x => length (fst c) + length (snd c) + x) 0 lt.

    Variables (c h l : pos n) (Hch : c <> h) (Hcl : c <> l) (Hhl : h <> l).
    Variables (p : nat)   (* jumps here when decoding worked correctly *)
              (q : nat)   (* jumps here when decoding produced an error *)
              .

    Let decoder_error := PUSH c Zero :: POP c q q :: nil.
    
    (* Code that implements a decoder for tile indices 
         - ll is a list of tiles (th,tl)
         
         - when c starts with a valid tile index in ll
           encoded as 00001 (with n 0s to represent b)
           then the corresponding tile is stacked into 
           h and l. The code ends up at s
           
         - otherwise, h and l are left unchanged and the
           code ends up at q
     *)

    Fixpoint decoder s i lt :=
      match lt with 
        | nil           => decoder_error
        | (th,tl) :: lt => POP c (3+length (tile h l th tl)+i) q ::
                           tile h l th tl ++
                           PUSH c Zero ::
                           POP c s s ::
                           decoder s (3+length (tile h l th tl)+i) lt 
      end.

    Fixpoint length_decoder lt :=
      match lt with
        | nil => 2
        | (th,tl) :: lt => 3+length th+length tl+length_decoder lt 
      end.
  
    Fact decoder_length s i lt : length (decoder s i lt) = length_decoder lt.
    Proof.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      revert s i; induction lt as [ | (th,tl) lt IHlt ]; intros s i; rew length; auto.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      simpl; rew length; rewrite IHlt; omega.
    Qed.

    Fact length_decoder_size lt : length_decoder lt = 2+3*length lt+size_cards lt.
    Proof. induction lt as [ | [] ]; simpl; auto; omega. Qed.

    Local Fact decoder_spec_rec s i mm ll th tl lr lc v w :
           v#>c  = list_repeat Zero (length ll) ++ One :: lc
        -> mm = ll++(th,tl)::lr
        -> w = (s,v[lc/c][(th++v#>h)/h][(tl++v#>l)/l])
        -> (i,decoder s i mm) // (i,v) ->> w.
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) (_ : @eq (list (prod (list bool) (list bool))) mm (@app (prod (list bool) (list bool)) ll (@cons (prod (list bool) (list bool)) (@pair (list bool) (list bool) th tl) lr))) (_ : @eq (prod nat (vec (list bool) n)) w (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i mm)) (@pair nat (vec (list bool) n) i v) w *)
      revert i mm th tl lr lc v w.
(* Goal: forall (i : nat) (mm : list (prod (list bool) (list bool))) (th tl : list bool) (lr : list (prod (list bool) (list bool))) (lc : list bool) (v : vec (list bool) n) (w : prod nat (vec (list bool) n)) (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) (_ : @eq (list (prod (list bool) (list bool))) mm (@app (prod (list bool) (list bool)) ll (@cons (prod (list bool) (list bool)) (@pair (list bool) (list bool) th tl) lr))) (_ : @eq (prod nat (vec (list bool) n)) w (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i mm)) (@pair nat (vec (list bool) n) i v) w *)
      induction ll as [ | (t1,t2) ll IHll ]; simpl; intros i mm th tl lr lc v w H1 H2 H3; subst w.

      (* The list ll is empty *)

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i mm)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i mm)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
      subst mm; simpl decoder.
      bsm sss POP 1 with c (S (S (S (length (tile h l th tl) + i)))) q lc.

      apply subcode_sss_compute_trans with (P := (1+i,tile h l th tl))
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
                                           (st2 := (1+length (tile h l th tl)+i,v[lc/c][(th++v#>h)/h][(tl++v#>l)/l])); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply tile_spec; auto.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      rew length; omega.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) l))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (S (S (S (Init.Nat.add (@length (bsm_instr n) (tile h l th tl)) i)))) q) (@app (bsm_instr n) (tile h l th tl) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (S (S (S (Init.Nat.add (@length (bsm_instr n) (tile h l th tl)) i)))) lr)))))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add (S O) (@length (bsm_instr n) (tile h l th tl))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i mm)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
      apply vec_pos_ext; intros z; dest z l.
   
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S O)))) i) (@vec_change (list bool) n v c lc)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      bsm sss PUSH with c Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with c s s lc; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v c lc) c (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) c))) v *)
      apply vec_pos_ext; intros z; dest z c.

      (* The list ll is not empty *)

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i mm)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
      subst mm; simpl.
      bsm sss POP 0 with c (S (S (S (length (tile h l t1 t2) + i)))) q (list_repeat Zero (length ll) ++ One :: lc).
      apply subcode_sss_compute with (P := (3+length (tile h l t1 t2)+i, 
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
                                            decoder s (S (S (S (length (tile h l t1 t2)+i)))) (ll++(th,tl)::lr))); auto.
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply IHll with th tl lr lc; auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      rew vec.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v c lc) c (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) c))) v *)
      apply vec_pos_ext; intros z; dest z c.
    Qed.

    Fact decoder_spec_ok s i ll th tl lr lc v st :
           v#>c = list_repeat Zero (length ll) ++ One :: lc
        -> st = (s,v[lc/c][(th++v#>h)/h][(tl++v#>l)/l])
        -> (i,decoder s i (ll++(th,tl)::lr)) // (i,v) ->> st.
    Proof.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      intros; subst; apply decoder_spec_rec with ll th tl lr lc; auto.
    Qed.

    (* There is no trailing 1 *)

    Fact decoder_spec_nok_1 s i ll v k : 
           v#>c = list_repeat Zero k
        -> exists r, (i,decoder s i ll) // (i,v) ->> (q,v[(list_repeat Zero r)/c]).
    Proof.
(* Goal: forall _ : @eq (list bool) (@vec_pos (list bool) n v c) (@list_repeat bool false k), @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i ll)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@list_repeat bool false r)))) *)
      revert i v k.
(* Goal: forall (i : nat) (v : vec (list bool) n) (k : nat) (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@list_repeat bool false k)), @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i ll)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@list_repeat bool false r)))) *)
      induction ll as [ | (t1,t2) ll IHll ]; intros i v k H1.

(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i (@nil (prod (list bool) (list bool))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i (@cons (prod (list bool) (list bool)) (@pair (list bool) (list bool) t1 t2) ll))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      simpl; unfold decoder_error.
(* Goal: @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
      exists k.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S O)))) i) (@vec_change (list bool) n v c lc)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      bsm sss PUSH with c Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with c q q (v#>c); rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v c lc) c (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) c))) v *)
      apply vec_pos_ext; intros z; dest z c.

(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i (@cons (prod (list bool) (list bool)) (@pair (list bool) (list bool) t1 t2) ll))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      unfold decoder; fold decoder.
(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) q) (@app (bsm_instr n) (tile h l t1 t2) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) ll)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      destruct k as [ | k ].

(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) q) (@app (bsm_instr n) (tile h l t1 t2) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) ll)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@list_repeat bool false r)))) *)
(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) q) (@app (bsm_instr n) (tile h l t1 t2) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) ll)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@list_repeat bool false r)))) *)
      exists 0.
      bsm sss POP empty with c (3 + length (tile h l t1 t2) + i) q.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v c lc) c (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) c))) v *)
      f_equal; apply vec_pos_ext; intros z; dest z c.

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      simpl in H1.
      destruct (IHll (3 + length (tile h l t1 t2) + i) (v[(list_repeat Zero k)/c]) k)
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        as (r & Hr); rew vec.
(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) q) (@app (bsm_instr n) (tile h l t1 t2) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) ll)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      exists r.
      bsm sss POP 0 with c (3 + length (tile h l t1 t2) + i) q (list_repeat Zero k).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      revert Hr; rew vec; apply subcode_sss_compute; auto.
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
    Qed.

    (* There might be a trailing 1 but the list of 0s is too long *)

    Fact decoder_spec_nok_2 s i ll lc v k : 
           v#>c = list_repeat Zero k ++ lc
        -> length ll <= k
        -> exists r, (i,decoder s i ll) // (i,v) ->> (q,v[(list_repeat Zero r ++ lc)/c]).
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (@list_repeat bool false k) lc)) (_ : le (@length (prod (list bool) (list bool)) ll) k), @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i ll)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      revert i lc v k.
(* Goal: forall (i : nat) (lc : list bool) (v : vec (list bool) n) (k : nat) (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (@list_repeat bool false k) lc)) (_ : le (@length (prod (list bool) (list bool)) ll) k), @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i ll)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      induction ll as [ | (t1,t2) ll IHll ]; intros i lc v k H1 H2.

(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i (@nil (prod (list bool) (list bool))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i (@cons (prod (list bool) (list bool)) (@pair (list bool) (list bool) t1 t2) ll))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      simpl; unfold decoder_error.
(* Goal: @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
      exists k.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S O)))) i) (@vec_change (list bool) n v c lc)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      bsm sss PUSH with c Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with c q q (v#>c); rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      bsm sss stop.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v c lc) c (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) c))) v *)
      apply vec_pos_ext; intros z; dest z c.

(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (decoder s i (@cons (prod (list bool) (list bool)) (@pair (list bool) (list bool) t1 t2) ll))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      unfold decoder; fold decoder.
(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) q) (@app (bsm_instr n) (tile h l t1 t2) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) ll)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      destruct k as [ | k ].

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      simpl in H2; omega.

(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) q) (@app (bsm_instr n) (tile h l t1 t2) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) ll)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      simpl in H1, H2.
      destruct (IHll (3 + length (tile h l t1 t2) + i) lc (v[(list_repeat Zero k++lc)/c]) k)
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        as (r & Hr); rew vec.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      omega.
(* Goal: @ex nat (fun r : nat => @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) q) (@app (bsm_instr n) (tile h l t1 t2) (@cons (bsm_instr n) (@bsm_push n c false) (@cons (bsm_instr n) (@bsm_pop n c s s) (decoder s (Init.Nat.add (Init.Nat.add (S (S (S O))) (@length (bsm_instr n) (tile h l t1 t2))) i) ll)))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) lc)))) *)
      exists r.
      bsm sss POP 0 with c (3 + length (tile h l t1 t2) + i) q (list_repeat Zero k++lc).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      revert Hr; rew vec; apply subcode_sss_compute; auto.
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
    Qed.
    
    (* A full decoder of a list of boolean into a list a valid tile indices,
       stacking the tiles in h/l in the list on the run. 
       
       The following list of indices [5,3,0,2] is encoded as 000001 0001 1 001
       A valid list of booleans is an encoding of [n1,...,n_p] where each
       n_i is stricly less than length mm 
       
       If the encoding on the list of indices is incorrect in any way:
         - either not a list of indices
         - or some index is to big
       then the full decoder ends up at q.
       
       The empty list is not a valid list of tile indices 
       
     *)

    Definition full_decoder i ll :=
         POP c (4+i) p ::
         PUSH c One ::
         PUSH h Zero ::
         POP h (5+i) q ::
         PUSH c Zero ::
         decoder i (5+i) ll.

    Definition length_full_decoder ll := 5 + length_decoder ll.
    
    Fact full_decoder_length i ll : length (full_decoder i ll) = length_full_decoder ll.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
    Proof. unfold full_decoder, length_full_decoder; rew length; rewrite decoder_length; auto. Qed.

    Local Fact full_dec_start_spec_0 i lt v :
        v#>c = nil
     -> (i,full_decoder i lt) // (i,v) ->> (p,v).
    Proof.
(* Goal: forall _ : not (@eq (list bool) (@vec_pos (list bool) n v c) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      intros H1.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      unfold full_decoder; simpl in H1.
      bsm sss POP empty with c (4+i) p.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
    Qed.

    Local Fact full_dec_start_spec_1 i lt v :
        v#>c <> nil
     -> (i,full_decoder i lt) // (i,v) ->> (5+i,v).
    Proof.
(* Goal: forall _ : not (@eq (list bool) (@vec_pos (list bool) n v c) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      intros H1.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      case_eq (v#>c).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      intros; destruct H1; auto.
(* Goal: forall (b : bool) (l : list bool) (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@cons bool b l)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      clear H1.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      unfold full_decoder.
(* Goal: forall (b : bool) (l : list bool) (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@cons bool b l)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      intros [] lc Hlc.

      bsm sss POP 1 with c (4+i) p lc.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) i) (@vec_change (list bool) n v c lc)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      bsm sss PUSH with c One.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S O) i)) (@vec_change (list bool) n (@vec_change (list bool) n v c lc) c (@cons bool true (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) c)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      bsm sss PUSH with h Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      bsm sss POP 0 with h (5+i) q (v#>h); rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v c (@cons bool true lc)) h (@vec_pos (list bool) n v h)) v *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      apply vec_pos_ext; intros z; dest z h; dest z c.

      bsm sss POP 0 with c (4+i) p lc.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S O)))) i) (@vec_change (list bool) n v c lc)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      bsm sss PUSH with c Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n v c lc) c (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) c))) v *)
      apply vec_pos_ext; intros z; dest z c.
    Qed.
 
    Local Fact full_dec_spec_rec i ln lc lt v :
        v#>c = list_nat_bool ln ++ lc
     -> Forall (fun x => x < length lt) ln
     -> let (hh,ll) := tile_concat ln lt
     in (i,full_decoder i lt) // (i,v) ->> (i,v[lc/c][(hh++v#>h)/h][(ll++v#>l)/l]).
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (list_nat_bool ln) lc)) (_ : @Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      intros H1 H2; revert H2 v H1.
(* Goal: forall (_ : @Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (v : vec (list bool) n) (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (list_nat_bool ln) lc)), let (hh, ll) := tile_concat ln lt in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      induction 1 as [ | k ln Hk Hln IHln ]; intros v H1; simpl.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l))) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      bsm sss stop; f_equal.
(* Goal: @eq (vec (list bool) n) v (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@vec_pos (list bool) n v h)) l (@vec_pos (list bool) n v l)) *)
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      apply vec_pos_ext; intros z; dest z l; dest z h; dest z c.

(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      destruct (nth_split _ (nil,nil) Hk) as (ll & lr & H2 & H3).
(* Goal: let (hh, ll) := let (th, tl) := @nth (prod (list bool) (list bool)) k lt (@pair (list bool) (list bool) (@nil bool) (@nil bool)) in let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      revert H2; generalize (nth k lt (nil,nil)); intros (th, tl) H2.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      simpl in H1.
      specialize (IHln (v[(list_nat_bool ln ++ lc)/c][(th++v#>h)/h][(tl++v#>l)/l])).
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      spec in IHln; rew vec.
(* Goal: let (hh, ll) := let (hh, ll) := tile_concat ln lt in @pair (list bool) (list bool) (@app bool hh th) (@app bool ll tl) in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) *)
      destruct (tile_concat ln lt) as (thh,tll).
      
      apply sss_compute_trans with (st2 := (5+i,v)).
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool (@app bool thh th) (@vec_pos (list bool) n v h))) l (@app bool (@app bool tll tl) (@vec_pos (list bool) n v l)))) *)
      apply full_dec_start_spec_1.
(* Goal: not (@eq (list bool) (@vec_pos (list bool) n v c) (@nil bool)) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool (@app bool thh th) (@vec_pos (list bool) n v h))) l (@app bool (@app bool tll tl) (@vec_pos (list bool) n v l)))) *)
      rewrite H1; destruct k; discriminate.
     
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      unfold full_decoder.
      apply subcode_sss_compute_trans with (P := (5+i,decoder i (5 + i) lt)) 
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
           (st2 := (i,v[(list_nat_bool ln++lc)/c][(th++v#>h)/h][(tl++v#>l)/l])); auto.
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      subst lt; apply decoder_spec_ok with (list_nat_bool ln++lc); auto.
(* Goal: @eq (list bool) (@app bool (@rev bool l) (@cons bool b (@vec_pos (list bool) n v x))) (@app bool (@app bool (@rev bool l) (@cons bool b (@nil bool))) (@vec_pos (list bool) n v x)) *)
      rewrite H3; revert H1; solve list eq.

(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
      eq goal IHln; do 2 f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) c lc) h (@app bool thh (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) h))) l (@app bool tll (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) l))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool (@app bool thh th) (@vec_pos (list bool) n v h))) l (@app bool (@app bool tll tl) (@vec_pos (list bool) n v l))) *)
      apply vec_pos_ext; intros z. 
(* Goal: @eq (list bool) (@app bool (@rev bool l) (@cons bool b (@vec_pos (list bool) n v x))) (@app bool (@app bool (@rev bool l) (@cons bool b (@nil bool))) (@vec_pos (list bool) n v x)) *)
      dest z l; solve list eq.
(* Goal: @eq (list bool) (@app bool (@rev bool l) (@cons bool b (@vec_pos (list bool) n v x))) (@app bool (@app bool (@rev bool l) (@cons bool b (@nil bool))) (@vec_pos (list bool) n v x)) *)
      dest z h; solve list eq.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l))) c lc) z) (@vec_pos (list bool) n (@vec_change (list bool) n v c lc) z) *)
      dest z c.
    Qed.

    (* Correctness lemma for the full decoder when
       then input actually encodes a valid list of tiles *)

    Theorem full_decoder_ok_spec i ln lt v :
        v#>c = list_nat_bool ln
     -> v#>h = nil
     -> v#>l = nil
     -> Forall (fun x => x < length lt) ln
     -> let (hh,ll) := tile_concat ln lt
     in (i,full_decoder i lt) // (i,v) ->> (p,v[nil/c][hh/h][ll/l]).
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v s) (@cons bool false (@nil bool))) (_ : @eq (list bool) (@vec_pos (list bool) n v h) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v l) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v a) (@nil bool)) (_ : tiles_solvable lt), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x s)) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
      intros H1 H2 H3 H4.
(* Goal: let (hh, ll) := tile_concat ln lt in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@nil bool)) h hh) l ll)) *)
      rewrite app_nil_end in H1.
(* Goal: let (hh, ll) := tile_concat ln lt in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@nil bool)) h hh) l ll)) *)
      generalize (@full_dec_spec_rec i ln nil lt v H1 H4).
(* Goal: forall _ : let (hh, ll) := tile_concat ln lt in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@nil bool)) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))), let (hh, ll) := tile_concat ln lt in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@nil bool)) h hh) l ll)) *)
      destruct (tile_concat ln lt) as (hh,ll).
(* Goal: not (@eq (list nat) ln (@nil nat)) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
      intros E.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply sss_compute_trans with (1 := E); auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@nil bool)) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@nil bool)) h hh) l ll)) *)
      rewrite H2, H3; repeat rewrite <- app_nil_end.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      apply full_dec_start_spec_0; rew vec.
    Qed.
 
    Local Fact full_dec_spec_rec1 i ln lc lt v :
        v#>c = list_nat_bool ln ++ lc
     -> Exists (fun x => length lt <= x) ln
     -> exists w, (i,full_decoder i lt) // (i,v) ->> (q,w)
               /\ forall z, z <> c -> z <> h -> z <> l -> v#>z = w#>z.
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (list_nat_bool ln) lc)) (_ : @Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      intros H1 H2; revert H2 v H1.
(* Goal: forall (_ : @Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (v : vec (list bool) n) (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (list_nat_bool ln) lc)), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      induction ln as [ | x ln IHln ]; intros Hln v H1.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      inversion Hln.

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      generalize (full_dec_start_spec_1 i lt v).
(* Goal: forall _ : forall _ : not (@eq (list bool) (@vec_pos (list bool) n v c) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      intros H2; spec in H2.
(* Goal: not (@eq (list bool) (@vec_pos (list bool) n v c) (@nil bool)) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      rewrite H1; simpl; destruct x; discriminate.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      simpl in H1.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      destruct (le_lt_dec (length lt) x) as [ Hx | Hx ].

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      unfold full_decoder.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z) *)
      solve list eq in H1.
      destruct (decoder_spec_nok_2 i (5+i) lt _ _ H1 Hx) as (r & Hr).
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
      exists (v [(list_repeat Zero r++One::list_nat_bool ln++lc)/c]); split.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply sss_compute_trans with (1 := H2); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      unfold full_decoder; revert Hr; apply subcode_sss_compute; auto.
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros; rew vec.

(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      apply Exists_cons in Hln.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      destruct Hln as [ Hln | Hln ].
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      omega.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      specialize (IHln Hln).
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      destruct (nth_split _ (nil,nil) Hx) as (ll & lr & H3 & H4).
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      revert H3; generalize (nth x lt (nil,nil)); intros (th, tl) H3.
      specialize (IHln (v[(list_nat_bool ln++lc)/c][(th++v#>h)/h][(tl++v#>l)/l])).
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      spec in IHln; rew vec.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      destruct IHln as (w & Hw & Hw1).
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
      exists w; split.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z) *)
      apply sss_compute_trans with (2 := Hw).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply sss_compute_trans with (1 := H2); auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z) *)
      rewrite <- H4 in H1.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z) *)
      solve list eq in H1.
      generalize (@decoder_spec_ok i (5+i) ll th tl lr _ _ _ H1 eq_refl).
(* Goal: forall _ : @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) (@app (prod (list bool) (list bool)) ll (@cons (prod (list bool) (list bool)) (@pair (list bool) (list bool) th tl) lr)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (list_nat_bool ln) lc)) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z) *)
      unfold full_decoder; apply subcode_sss_compute.
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subst; subcode_tac; solve list eq.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros z G1 G2 G3; generalize (Hw1 _ G1 G2 G3); rew vec.
    Qed.

    Local Fact full_dec_spec_rec2 i k lt v :
        v#>c = list_repeat Zero (S k)
     -> exists w, (i,full_decoder i lt) // (i,v) ->> (q,w)
               /\ forall z, z <> c -> z <> h -> z <> l -> v#>z = w#>z.
    Proof.
      intros H.
      destruct (@decoder_spec_nok_1 i (5+i) lt _ _ H) as (r & Hr).
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
      exists (v[(list_repeat Zero r)/c]); split.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      2: intros; rew vec.
(* Goal: forall _ : not (@eq (list bool) (@vec_pos (list bool) n v c) (@nil bool)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S O))))) i) v) *)
      generalize (@full_dec_start_spec_1 i lt v); intros H1.
      spec in H1.
      rewrite H; discriminate.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply sss_compute_trans with (1 := H1); auto.
      revert Hr.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      unfold full_decoder.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply subcode_sss_compute; auto.
(* Goal: @subcode (bsm_instr n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S O))))) i) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt)) (@pair nat (list (bsm_instr n)) i (@cons (bsm_instr n) (@bsm_pop n c (Init.Nat.add (S (S (S (S O)))) i) p) (@cons (bsm_instr n) (@bsm_push n c true) (@cons (bsm_instr n) (@bsm_push n h false) (@cons (bsm_instr n) (@bsm_pop n h (Init.Nat.add (S (S (S (S (S O))))) i) q) (@cons (bsm_instr n) (@bsm_push n c false) (decoder i (Init.Nat.add (S (S (S (S (S O))))) i) lt))))))) *)
(* Goal: forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false r) (@cons bool true (@app bool (list_nat_bool ln) lc)))) z) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      subcode_tac; solve list eq.
    Qed.
    
    (* Correctness lemma for the full decoder when
       then input encodes an invalid list of tiles *)

    Theorem full_decoder_ko_spec i ln lc lt v :
         v#>c = list_nat_bool ln ++ lc
     -> (Exists (fun x => length lt <= x) ln
     \/  Forall (fun x => x < length lt) ln 
      /\ exists k, lc = list_repeat Zero (S k))
     ->  exists w, (i,full_decoder i lt) // (i,v) ->> (q,w)
               /\ forall z, z <> c -> z <> h -> z <> l -> v#>z = w#>z.
    Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v c) (@app bool (list_nat_bool ln) lc)) (_ : or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      intros H1 [ H2 | (H2 & k & H3) ].
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply full_dec_spec_rec1 with ln lc; auto.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      generalize (@full_dec_spec_rec i ln lc lt v H1 H2).
(* Goal: forall _ : let (hh, ll) := tile_concat ln lt in @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool hh (@vec_pos (list bool) n v h))) l (@app bool ll (@vec_pos (list bool) n v l)))), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
      destruct (tile_concat ln lt) as (hh,ll); intros H4.
      destruct (@full_dec_spec_rec2 i k lt 
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
           (v[lc/c][(hh++v#>h)/h][(ll++v#>l)/l])) as (w & Hw1 & Hw2); rew vec.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
      exists w; split.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      apply sss_compute_trans with (1 := H4); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
      intros x E1 E2 E3; rewrite <- Hw2; auto; rew vec.
    Qed.

  End full_decoder.

  Hint Rewrite full_decoder_length : length_db.

  Section simulator.

    Variables (s a h l : pos n) (Hsa : s <> a) (Hsh : s <> h) (Hsl : s <> l)
                                (Hah : a <> h) (Hal : a <> l) (Hhl : h <> l)
              (lt : list ((list bool)*list bool)).

    Section increment_erase.
      
      Variable (i p : nat).
      
      (* This code does the following 
         - increments s (as a list of booleans)
         - empties h, l and a
         - jumps to p
       *)

      Definition increment_erase :=
      (*      i *) increment s a i ++
      (*   15+i *) empty_stack h (15+i) ++
      (*   18+i *) empty_stack l (18+i) ++
      (*   21+i *) empty_stack a (21+i) ++
      (*   24+i *) PUSH l Zero :: POP l p p :: nil.

      Fact increment_erase_length : length increment_erase = 26.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      Proof. auto. Qed.

      Fact increment_erase_spec v ln mn w :
           list_bool_succ ln mn
        -> v#>s = ln 
        -> w = v[mn/s][nil/h][nil/l][nil/a]
        -> (i,increment_erase) // (i,v) ->> (p,w).
      Proof.
(* Goal: forall (_ : list_bool_succ ln mn) (_ : @eq (list bool) (@vec_pos (list bool) n v s) ln) (_ : @eq (vec (list bool) n) w (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i increment_erase) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w) *)
        intros H1 H2 ?; subst w.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i increment_erase) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
        unfold increment_erase.

        apply sss_compute_trans with (st2 := (15+i,v[mn/s])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (i,increment s a i )); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply increment_spec with ln; auto.

        apply sss_compute_trans with (st2 := (18+i,v[mn/s][nil/h])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (15+i,empty_stack h (15+i))); auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i) (empty_stack a (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (increment s a i) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))) i)) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i)) (@cons (bsm_instr n) (@bsm_push n l false) (@cons (bsm_instr n) (@bsm_pop n l p p) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
        apply empty_stack_spec.

        apply sss_compute_trans with (st2 := (21+i,v[mn/s][nil/h][nil/l])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (18+i,empty_stack l (18+i))); auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i) (empty_stack a (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (increment s a i) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))) i)) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i)) (@cons (bsm_instr n) (@bsm_push n l false) (@cons (bsm_instr n) (@bsm_pop n l p p) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
        apply empty_stack_spec.
        
        apply sss_compute_trans with (st2 := (24+i,v[mn/s][nil/h][nil/l][nil/a])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (21+i,empty_stack a (21+i))); auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i) (empty_stack a (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (increment s a i) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))) i)) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i)) (@cons (bsm_instr n) (@bsm_push n l false) (@cons (bsm_instr n) (@bsm_pop n l p p) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
        apply empty_stack_spec.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (increment s a i) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))) i)) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))) i)) (@cons (bsm_instr n) (@bsm_push n l false) (@cons (bsm_instr n) (@bsm_pop n l p p) (@nil (bsm_instr n))))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) (@pair nat (vec (list bool) n) p (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool))) *)
        bsm sss PUSH with l Zero.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        bsm sss POP 0 with l p p nil; rew vec.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        bsm sss stop.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool)) l (@nil bool)) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s mn) h (@nil bool)) l (@nil bool)) a (@nil bool)) *)
        apply vec_pos_ext; intros x; dest x l.
      Qed.

    End increment_erase.

    Hint Rewrite increment_erase_length : length_db.
    
    Section main_init.
      
      Variable (i : nat).
      
      (* Self explaining code:
          - s becomes Zero::nil
          - a, h and l are emptied 
       *)

      Definition main_init :=
      (*      i *) empty_stack s i ++
      (*    3+i *) empty_stack a (3+i) ++
      (*    6+i *) empty_stack h (6+i) ++
      (*    9+i *) empty_stack l (9+i) ++
      (*   12+i *) PUSH s Zero :: nil.

      Fact main_init_length : length main_init = 13.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
      Proof. auto. Qed.

      Fact main_init_spec v : (i,main_init) // (i,v) ->> (13+i,v[(Zero::nil)/s][nil/a][nil/h][nil/l]).
      Proof.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_init) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        unfold main_init.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute_trans with (2 := empty_stack_spec s _ _); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute_trans with (2 := empty_stack_spec a _ _); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute_trans with (2 := empty_stack_spec h (6+i) _); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute_trans with (2 := empty_stack_spec l (9+i) _); auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        bsm sss PUSH with s Zero.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (empty_stack s i) (@app (bsm_instr n) (empty_stack a (Init.Nat.add (S (S (S O))) i)) (@app (bsm_instr n) (empty_stack h (Init.Nat.add (S (S (S (S (S (S O)))))) i)) (@app (bsm_instr n) (empty_stack l (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i)) (@cons (bsm_instr n) (@bsm_push n s false) (@nil (bsm_instr n)))))))) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        bsm sss stop.
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) (Init.Nat.add (S O) (Init.Nat.add (S (S (S O))) (Init.Nat.add (S (S (S (S (S (S (S (S (S O))))))))) i))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s (@cons bool false (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@nil bool)) a (@nil bool)) h (@nil bool)) l (@nil bool)) s)))) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v s (@cons bool false (@nil bool))) a (@nil bool)) h (@nil bool)) l (@nil bool))) *)
        f_equal.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n w s (list_bool_next (@vec_pos (list bool) n v s))) h (@nil bool)) l (@nil bool)) a (@nil bool)) *)
        apply vec_pos_ext; intros x.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s))) x) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n w s (list_bool_next (@vec_pos (list bool) n v s))) h (@nil bool)) l (@nil bool)) a (@nil bool)) x) *)
        dest x a; dest x l; dest x h; dest x s.
      Qed.
 
    End main_init.

    Section main_loop.

      Variables (i p : nat).

      Let lFD := length_full_decoder lt.

      (* This code does the following:
           - copies s to a (temporarily using the empty h stack)
           - decodes a as a list of tiles into h/l
             * if the list is correct and h = l at the ends, we
               have a solution to PCP and we jump to p
             * if the list is incorrect, increments s, 
               clean up of h, l and a and start over (loop)
       *)

      Definition main_loop := 
      (*          i *) copy_stack s a h i ++
      (*       16+i *) full_decoder a h l (lFD+16+i) (lFD+26+i) (16+i) lt ++
      (*   lFD+16+i *) compare_stacks h l (lFD+16+i) p (lFD+26+i) ++
      (*   lFD+26+i *) increment_erase (lFD+26+i) i.

      Definition length_main_loop := 52 + lFD.

      Fact main_loop_length : length main_loop = length_main_loop.
      Proof. unfold main_loop, length_main_loop, lFD; rew length; omega. Qed.

      Fact main_loop_size : length_main_loop = 59+3*length lt+size_cards lt.
      Proof.
(* Goal: @eq nat length_main_loop (Init.Nat.add (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (Init.Nat.mul (S (S (S O))) (@length (prod (list bool) (list bool)) lt))) (size_cards lt)) *)
        unfold length_main_loop, lFD, length_full_decoder.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (full_decoder i lt)) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)) (forall (z : pos n) (_ : not (@eq (pos n) z c)) (_ : not (@eq (pos n) z h)) (_ : not (@eq (pos n) z l)), @eq (list bool) (@vec_pos (list bool) n v z) (@vec_pos (list bool) n w z))) *)
        rewrite length_decoder_size; omega.
      Qed.

      Fact main_loop_ok_spec v ln :
             v#>h = nil
          -> v#>l = nil
          -> v#>a = nil
          -> v#>s = list_nat_bool ln 
          -> Forall (fun x => x < length lt) ln
          -> (let (hh,ll) := tile_concat ln lt in hh = ll)
          -> exists w, (i,main_loop) // (i,v) ->> (p,w)
                    /\ forall x, x <> a -> x <> h -> x <> l -> v#>x = w#> x.
      Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v h) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v l) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v a) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v s) (list_nat_bool ln)) (_ : @Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (_ : let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
        intros H0 H1 H2 H3 H4 H5.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        case_eq (tile_concat ln lt).
(* Goal: forall (l0 l1 : list bool) (_ : @eq (prod (list bool) (list bool)) (tile_concat ln lt) (@pair (list bool) (list bool) l0 l1)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        intros hh ll E; rewrite E in H5.
        destruct (compare_stack_eq_spec Hhl (lFD+16+i) p (lFD+26+i) (v[nil/a][hh/h][ll/l]))
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
          as (w & Hw1 & Hw2); rew vec.
(* Goal: @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
        exists w; split.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        unfold main_loop.

        apply sss_compute_trans with (st2 := (16+i,v[(list_nat_bool ln)/a])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (i,copy_stack s a h i)); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply copy_stack_spec with (list_nat_bool ln); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        rewrite H2, <- app_nil_end; auto.

        apply sss_compute_trans with (st2 := (lFD+16+i,v[nil/a][hh/h][ll/l])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (16+i,full_decoder a h l (lFD+16+i) (lFD+26+i) (16+i) lt)); auto.
        generalize (@full_decoder_ok_spec _ _ _ Hah Hal Hhl (lFD+16+i) (lFD+26+i) (16+i) ln lt
          (v[(list_nat_bool ln)/a])); intros H6.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (@vec_change (list bool) n v a (list_nat_bool ln))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        do 3 (spec in H6; [ rew vec | ]).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        spec in H6; auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (@vec_change (list bool) n v a (list_nat_bool ln))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        rewrite E in H6.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        eq goal H6; do 2 f_equal; rew vec.

(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (lFD+16+i,compare_stacks h l (lFD+16+i) p (lFD+26+i))); auto.

(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        intros x E1 E2 E3; generalize (Hw2 _ E2 E3); rew vec.
      Qed.

      Fact main_loop_ko_spec v ln lc :
             v#>h = nil
          -> v#>l = nil
          -> v#>a = nil
          -> v#>s = list_nat_bool ln ++ lc
          -> (  (   Exists (fun x => length lt <= x) ln
                \/  Forall (fun x => x < length lt) ln /\ exists k, lc = list_repeat Zero (S k) )
             \/  Forall (fun x => x < length lt) ln /\ lc = nil 
                 /\ let (hh,ll) := tile_concat ln lt in hh <> ll)
          -> (i,main_loop) // (i,v) ->> (i,v[(list_bool_next (v#>s))/s]). 
      Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v h) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v l) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v a) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v s) (@app bool (list_nat_bool ln) lc)) (_ : or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll))))), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        intros H0 H1 H2 H3 [ H4 | (H4 & ? & H5) ].
        
        destruct (@full_decoder_ko_spec _ _ _ Hah Hal Hhl (lFD+16+i) (lFD+26+i) (16+i)) 
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
          with (v := v[(list_nat_bool ln ++ lc)/a]) (2 := H4) as (w & Hw1 & Hw2); rew vec.

(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        unfold main_loop. 
        apply sss_compute_trans with (st2 := (16+i,v[(list_nat_bool ln++lc)/a])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (i,copy_stack s a h i)); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply copy_stack_spec with (list_nat_bool ln++lc); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        rewrite H2, <- app_nil_end; auto.

(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute_trans with (2 := Hw1); auto. 

(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (lFD+26+i,increment_erase (lFD + 26 + i) i)); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply increment_erase_spec with (1 := list_bool_next_spec (v#>s)); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        rewrite <- Hw2; auto; rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n w s (list_bool_next (@vec_pos (list bool) n v s))) h (@nil bool)) l (@nil bool)) a (@nil bool)) *)
        apply vec_pos_ext; intros x.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s))) x) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n w s (list_bool_next (@vec_pos (list bool) n v s))) h (@nil bool)) l (@nil bool)) a (@nil bool)) x) *)
        dest x a; dest x l; dest x h; dest x s.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        rewrite <- Hw2; auto; rew vec.
        
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        unfold main_loop.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        subst lc.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        rewrite <- app_nil_end in H3.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        case_eq (tile_concat ln lt).
(* Goal: forall (l0 l1 : list bool) (_ : @eq (prod (list bool) (list bool)) (tile_concat ln lt) (@pair (list bool) (list bool) l0 l1)), @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        intros hh ll E; rewrite E in H5.
        destruct (compare_stack_neq_spec Hhl (lFD+16+i) p (lFD+26+i) (v[nil/a][hh/h][ll/l]))
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
          as (w & Hw1 & Hw2); rew vec.

        apply sss_compute_trans with (st2 := (16+i,v[(list_nat_bool ln)/a])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (i,copy_stack s a h i)); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply copy_stack_spec with (list_nat_bool ln); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        rewrite H2, <- app_nil_end; auto.

        apply sss_compute_trans with (st2 := (lFD+16+i,v[nil/a][hh/h][ll/l])).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (16+i,full_decoder a h l (lFD+16+i) (lFD+26+i) (16+i) lt)); auto.
        generalize (@full_decoder_ok_spec _ _ _ Hah Hal Hhl (lFD+16+i) (lFD+26+i) (16+i) ln lt
          (v[(list_nat_bool ln)/a])); intros H6.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (@vec_change (list bool) n v a (list_nat_bool ln))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        do 3 (spec in H6; [ rew vec | ]).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        spec in H6; auto.
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt)) (@pair nat (vec (list bool) n) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) (@vec_change (list bool) n v a (list_nat_bool ln))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) *)
(* Goal: @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i (@app (bsm_instr n) (copy_stack s a h i) (@app (bsm_instr n) (full_decoder a h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) (Init.Nat.add (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O)))))))))))))))) i) lt) (@app (bsm_instr n) (compare_stacks h l (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) p (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i)) (increment_erase (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))) i) i))))) (@pair nat (vec (list bool) n) (Init.Nat.add (Init.Nat.add lFD (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))) i) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v a (@nil bool)) h hh) l ll)) (@pair nat (vec (list bool) n) i (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s)))) *)
        rewrite E in H6.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        eq goal H6; do 2 f_equal; rew vec.
        
        apply sss_compute_trans with (st2 := (lFD+26+i,w)).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (lFD+16+i,compare_stacks h l (lFD+16+i) p (lFD+26+i))); auto.
 
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply subcode_sss_compute with (P := (lFD+26+i,increment_erase (lFD + 26 + i) i)); auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply increment_erase_spec with (1 := list_bool_next_spec (v#>s)); auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        rewrite <- Hw2; auto; rew vec.
(* Goal: @eq (vec (list bool) n) (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s))) (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n w s (list_bool_next (@vec_pos (list bool) n v s))) h (@nil bool)) l (@nil bool)) a (@nil bool)) *)
        apply vec_pos_ext; intros x.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v s (list_bool_next (@vec_pos (list bool) n v s))) x) (@vec_pos (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n w s (list_bool_next (@vec_pos (list bool) n v s))) h (@nil bool)) l (@nil bool)) a (@nil bool)) x) *)
        dest x a; dest x l; dest x h; dest x s.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        rewrite <- Hw2; auto; rew vec.
      Qed.

      Implicit Type (v : vec (list bool) n).
      
      Let pre v := v#>h = nil /\ v#>l = nil /\ v#>a = nil.
      Let spec v w := forall x, x <> a -> x <> h -> x <> l -> v#>x = w#> x.
      Let f v := v[(list_bool_next (v#>s))/s].

      Let Hf v : v <> f v.
      Proof.
(* Goal: not (@eq (list nat) ln (@nil nat)) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        intros E.
(* Goal: False *)
        apply (list_bool_succ_neq) with (1 := list_bool_next_spec (v#>s)).
(* Goal: @eq (list bool) (@vec_pos (list bool) n v s) (list_bool_next (@vec_pos (list bool) n v s)) *)
        rewrite E at 1.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        unfold f; rew vec.
      Qed.

      Let C2 v := exists ln, 
             v#>s = list_nat_bool ln 
          /\ Forall (fun x => x < length lt) ln
          /\ (let (hh,ll) := tile_concat ln lt in hh = ll).

      Let C1 v :=  exists ln lc,
             v#>s = list_nat_bool ln ++ lc
          /\ (  (   Exists (fun x => length lt <= x) ln
                \/  Forall (fun x => x < length lt) ln /\ exists k, lc = list_repeat Zero (S k) )
             \/  Forall (fun x => x < length lt) ln /\ lc = nil 
                 /\ let (hh,ll) := tile_concat ln lt in hh <> ll).

      Let HC v : pre v -> { C1 v } + { C2 v }.
      Proof.
(* Goal: forall _ : pre v, sumbool (C1 v) (C2 v) *)
        unfold C1, C2.
(* Goal: forall _ : pre v, sumbool (@ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) (@vec_pos (list bool) n v s) (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll)))))))) (@ex (list nat) (fun ln : list nat => and (@eq (list bool) (@vec_pos (list bool) n v s) (list_nat_bool ln)) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
        intros _.
(* Goal: sumbool (@ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) (@vec_pos (list bool) n v s) (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll)))))))) (@ex (list nat) (fun ln : list nat => and (@eq (list bool) (@vec_pos (list bool) n v s) (list_nat_bool ln)) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
        generalize (v#>s); clear v; intros m.
        destruct (list_bool_valid_dec (length lt) m)
          as [ (ln & H1) | (ln & H1) ].
(* Goal: sumbool (@ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll)))))))) (@ex (list nat) (fun ln : list nat => and (@eq (list bool) m (list_nat_bool ln)) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
(* Goal: sumbool (@ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll)))))))) (@ex (list nat) (fun ln : list nat => and (@eq (list bool) m (list_nat_bool ln)) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
        case_eq (tile_concat ln lt); intros hh ll H2.
(* Goal: sumbool (@ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll)))))))) (@ex (list nat) (fun ln : list nat => and (@eq (list bool) m (list_nat_bool ln)) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
(* Goal: sumbool (@ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll)))))))) (@ex (list nat) (fun ln : list nat => and (@eq (list bool) m (list_nat_bool ln)) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
        destruct (list_bool_dec hh ll) as [ H3 | H3 ].
        * right.
(* Goal: @ex (list nat) (fun ln : list nat => and (@eq (list bool) m (list_nat_bool ln)) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))) *)
          exists ln.
(* Goal: @ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll))))))) *)
          destruct H1 as (H1 & H4).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
          rewrite H2; auto.
        * left.
(* Goal: @ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll))))))) *)
          destruct H1 as (H1 & H4).
(* Goal: @ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll))))))) *)
          exists ln, nil.
(* Goal: and (@eq (list bool) m (@app bool (list_nat_bool ln) (@nil bool))) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) (@nil bool) (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) (@nil bool) (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll))))) *)
          rewrite <- app_nil_end.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
          split; auto.
(* Goal: or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) (@nil bool) (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) (@nil bool) (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll)))) *)
          right.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
          rewrite H2; auto.
        * left.
(* Goal: @ex (list nat) (fun ln : list nat => @ex (list bool) (fun lc : list bool => and (@eq (list bool) m (@app bool (list_nat_bool ln) lc)) (or (or (@Exists nat (fun x : nat => le (@length (prod (list bool) (list bool)) lt) x) ln) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (@ex nat (fun k : nat => @eq (list bool) lc (@list_repeat bool false (S k)))))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (and (@eq (list bool) lc (@nil bool)) (let (hh, ll) := tile_concat ln lt in not (@eq (list bool) hh ll))))))) *)
          destruct H1 as (lc & H1 & H2).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
          exists ln, lc; split; auto.
      Qed.

      Hypothesis (Hp : out_code p (i,main_loop)).

      Let HP1 : forall x, pre x -> C1 x -> (i,main_loop) // (i,x) ->> (i,f x) /\ pre (f x).
      Proof.
(* Goal: forall (x : vec (list bool) n) (_ : pre x) (_ : C1 x), and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i x) (@pair nat (vec (list bool) n) i (f x))) (pre (f x)) *)
        intros v (H1 & H2 & H3) (ln & lc & H4 & H5).
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
        split.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply main_loop_ko_spec with ln lc; auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        red; unfold f; rew vec; auto.
      Qed.

      Let HP2 : forall x, pre x -> C2 x -> exists y, (i,main_loop) // (i,x) ->> (p,y) /\ spec x y.
      Proof.
(* Goal: forall (x : vec (list bool) n) (_ : pre x) (_ : C2 x), @ex (vec (list bool) n) (fun y : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i x) (@pair nat (vec (list bool) n) p y)) (spec x y)) *)
        intros v (H1 & H2 & H3) (ln & H4 & H5 & H6).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply  main_loop_ok_spec with ln; auto.
      Qed.

      Let main_loop_sound_rec v :
                pre v
             -> (exists n, C2 (iter f v n)) 
             -> exists n w, (i,main_loop) // (i,v) ->> (p,w) /\ spec (iter f v n) w.
      Proof.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply sss_loop_sound with (C1 := C1); auto.
      Qed.

      Let main_loop_complete_rec v w q : pre v 
                                      -> out_code q (i,main_loop) 
                                      -> (i,main_loop) // (i,v) ->> (q,w) 
                                      -> p = q /\ exists n, C2 (iter f v n) /\ spec (iter f v n) w.
      Proof.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        apply sss_loop_complete with (C1 := C1); auto.
(* Goal: forall (i : bsm_instr n) (s t1 t2 : prod nat (vec (list bool) n)) (_ : @bsm_sss n i s t1) (_ : @bsm_sss n i s t2), @eq (prod nat (vec (list bool) n)) t1 t2 *)
        apply bsm_sss_fun.
      Qed.

      Let iter_f_v v k : iter f v k = v[(iter list_bool_next (v#>s) k)/s].
      Proof.
(* Goal: @eq (vec (list bool) n) (@iter (vec (list bool) n) f v k) (@vec_change (list bool) n v s (@iter (list bool) list_bool_next (@vec_pos (list bool) n v s) k)) *)
        revert v.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        unfold f; induction k as [ | k IHk ]; intros v; simpl; [ | rewrite IHk ]; rew vec.
      Qed.

      Let C2_eq v : v#>s = Zero::nil -> (exists n, C2 (iter f v n)) <-> tiles_solvable lt.
      Proof.
(* Goal: forall _ : @eq (list bool) (@vec_pos (list bool) n v s) (@cons bool false (@nil bool)), iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (tiles_solvable lt) *)
        unfold tiles_solvable.
(* Goal: forall _ : @eq (list bool) (@vec_pos (list bool) n v s) (@cons bool false (@nil bool)), iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
        intros H1; simpl.
(* Goal: iff (@ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0))) (@ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll)))) *)
        split.

(* Goal: forall _ : @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)), @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        intros (k & Hk).
(* Goal: @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        rewrite iter_f_v, H1 in Hk.
(* Goal: @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        destruct Hk as (ln & H2 & H3 & H4).
(* Goal: @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        revert H2; rew vec; intros H2.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        exists ln; repeat split; auto.
(* Goal: not (@eq (list nat) ln (@nil nat)) *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        intros E.
(* Goal: False *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        subst ln.
(* Goal: False *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        simpl in H2.
(* Goal: False *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        apply iter_list_bool_next_nil in H2.
(* Goal: False *)
(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        destruct H2; discriminate.

(* Goal: forall _ : @ex (list nat) (fun ln : list nat => and (not (@eq (list nat) ln (@nil nat))) (and (@Forall nat (fun x : nat => Peano.lt x (@length (prod (list bool) (list bool)) lt)) ln) (let (hh, ll) := tile_concat ln lt in @eq (list bool) hh ll))), @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        intros (ln & H2 & H3 & H4).
(* Goal: @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        destruct (@list_bool_next_total (list_nat_bool ln)) as (k & Hk).
(* Goal: not (@eq (list bool) (list_nat_bool ln) (@nil bool)) *)
(* Goal: @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        destruct ln as [ | [ | u ] ln ]; simpl; auto; discriminate.
(* Goal: @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)) *)
        exists k.
(* Goal: C2 (@iter (vec (list bool) n) f v k) *)
        rewrite iter_f_v, H1, <- Hk.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        exists ln; rew vec; auto.
      Qed.

      Theorem main_loop_sound v :
          v#>s = Zero::nil -> v#>h = nil -> v#>l = nil -> v#>a = nil
       -> tiles_solvable lt
       -> exists w, (i,main_loop) // (i,v) ->> (p,w) 
                 /\ forall x, x <> s -> x <> a -> x <> h -> x <> l -> v#>x = w#>x.
      Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v s) (@cons bool false (@nil bool))) (_ : @eq (list bool) (@vec_pos (list bool) n v h) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v l) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v a) (@nil bool)) (_ : tiles_solvable lt), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x s)) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
        intros H1 H2 H3 H4.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        rewrite <- (C2_eq _ H1); auto.
(* Goal: forall _ : @ex nat (fun n0 : nat => C2 (@iter (vec (list bool) n) f v n0)), @ex (vec (list bool) n) (fun w : vec (list bool) n => and (@sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) p w)) (forall (x : pos n) (_ : not (@eq (pos n) x s)) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x))) *)
        intros H5.
        destruct main_loop_sound_rec with (2 := H5)
          as (k & w & Hw1 & Hw2).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        red; auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        exists w; split; auto.
        unfold spec in Hw2 |- *.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        intros; rewrite <- Hw2; auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        rewrite iter_f_v; rew vec.
      Qed.

      Theorem main_loop_complete v w q : 
          v#>s = Zero::nil -> v#>h = nil -> v#>l = nil -> v#>a = nil
       -> out_code q (i,main_loop)
       -> (i,main_loop) // (i,v) ->> (q,w) 
       -> p = q 
       /\ (forall x, x <> s -> x <> a -> x <> h -> x <> l -> v#>x = w#>x)
       /\ tiles_solvable lt.
      Proof.
(* Goal: forall (_ : @eq (list bool) (@vec_pos (list bool) n v s) (@cons bool false (@nil bool))) (_ : @eq (list bool) (@vec_pos (list bool) n v h) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v l) (@nil bool)) (_ : @eq (list bool) (@vec_pos (list bool) n v a) (@nil bool)) (_ : @out_code (bsm_instr n) q (@pair nat (list (bsm_instr n)) i main_loop)) (_ : @sss_compute (bsm_instr n) (vec (list bool) n) (@bsm_sss n) (@pair nat (list (bsm_instr n)) i main_loop) (@pair nat (vec (list bool) n) i v) (@pair nat (vec (list bool) n) q w)), and (@eq nat p q) (and (forall (x : pos n) (_ : not (@eq (pos n) x s)) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x)) (tiles_solvable lt)) *)
        intros H1 H2 H3 H4 H5 H6.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        rewrite  <- (C2_eq _ H1); auto.
        destruct main_loop_complete_rec with (2 := H5) (3 := H6)
          as (G1 & k & G2 & G3).
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        red; auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        split; auto.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        split; [ | exists k ]; auto.
(* Goal: forall (x : pos n) (_ : not (@eq (pos n) x s)) (_ : not (@eq (pos n) x a)) (_ : not (@eq (pos n) x h)) (_ : not (@eq (pos n) x l)), @eq (list bool) (@vec_pos (list bool) n v x) (@vec_pos (list bool) n w x) *)
        red in G3.
(* Goal: @eq nat (@length (bsm_instr n) main_init) (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))) *)
        intros; rewrite <- G3; auto.
(* Goal: @eq (list bool) (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c) (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc)) *)
(* Goal: @eq (prod nat (vec (list bool) n)) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c lc) h (@app bool th (@vec_pos (list bool) n v h))) l (@app bool tl (@vec_pos (list bool) n v l)))) (@pair nat (vec (list bool) n) s (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) c lc) h (@app bool th (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) h))) l (@app bool tl (@vec_pos (list bool) n (@vec_change (list bool) n v c (@app bool (@list_repeat bool false (@length (prod (list bool) (list bool)) ll)) (@cons bool true lc))) l)))) *)
        rewrite iter_f_v; rew vec.
      Qed.

    End main_loop.
    
  End simulator.
    
End Binary_Stack_Machines.
