(* The following predicate makes it easier for us to do induction on the number of loop iterations. *)
Inductive evalDet_repeat_steps (A : Set)(P : A -> bool) : comp_state A -> comp_state A -> Prop :=
| evalDet_repeat_steps_done : 
  forall c s a s',
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = true ->
    evalDet_repeat_steps P (cs_more c s) (cs_done a s')
| evalDet_repeat_steps_eof :
  forall c s,
    evalDet_steps (cs_more c s) (@cs_eof A) ->
    evalDet_repeat_steps P (cs_more c s) (@cs_eof A)
| evalDet_repeat_steps_step :
  forall c s a s' y,
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = false ->
    evalDet_repeat_steps P (cs_more c s') y ->
    evalDet_repeat_steps P (cs_more c s) y.(* The following predicate makes it easier for us to do induction on the number of loop iterations. *)
Inductive evalDet_repeat_steps (A : Set)(P : A -> bool) : comp_state A -> comp_state A -> Prop :=
| evalDet_repeat_steps_done : 
  forall c s a s',
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = true ->
    evalDet_repeat_steps P (cs_more c s) (cs_done a s')
| evalDet_repeat_steps_eof :
  forall c s,
    evalDet_steps (cs_more c s) (@cs_eof A) ->
    evalDet_repeat_steps P (cs_more c s) (@cs_eof A)
| evalDet_repeat_steps_step :
  forall c s a s' y,
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = false ->
    evalDet_repeat_steps P (cs_more c s') y ->
    evalDet_repeat_steps P (cs_more c s) y.(* The following predicate makes it easier for us to do induction on the number of loop iterations. *)
Inductive evalDet_repeat_steps (A : Set)(P : A -> bool) : comp_state A -> comp_state A -> Prop :=
| evalDet_repeat_steps_done : 
  forall c s a s',
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = true ->
    evalDet_repeat_steps P (cs_more c s) (cs_done a s')
| evalDet_repeat_steps_eof :
  forall c s,
    evalDet_steps (cs_more c s) (@cs_eof A) ->
    evalDet_repeat_steps P (cs_more c s) (@cs_eof A)
| evalDet_repeat_steps_step :
  forall c s a s' y,
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = false ->
    evalDet_repeat_steps P (cs_more c s') y ->
    evalDet_repeat_steps P (cs_more c s) y.(* The following predicate makes it easier for us to do induction on the number of loop iterations. *)
Inductive evalDet_repeat_steps (A : Set)(P : A -> bool) : comp_state A -> comp_state A -> Prop :=
| evalDet_repeat_steps_done : 
  forall c s a s',
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = true ->
    evalDet_repeat_steps P (cs_more c s) (cs_done a s')
| evalDet_repeat_steps_eof :
  forall c s,
    evalDet_steps (cs_more c s) (@cs_eof A) ->
    evalDet_repeat_steps P (cs_more c s) (@cs_eof A)
| evalDet_repeat_steps_step :
  forall c s a s' y,
    evalDet_steps (cs_more c s) (cs_done a s') ->
    P a = false ->
    evalDet_repeat_steps P (cs_more c s') y ->
    evalDet_repeat_steps P (cs_more c s) y.Inductive evalDet_repeat(A : Set)(P : A -> bool)(c : Comp A)(s : Blist) : comp_answer A -> Prop :=
  | evalDet_repeat_done : forall a s',
    evalDet_repeat_steps P (cs_more c s) (cs_done a s') ->
    evalDet_repeat P c s (ca_done a)
  | evalDet_repeat_eof :
    evalDet_repeat_steps P (cs_more c s) (@cs_eof A) ->
    evalDet_repeat P c s (@ca_eof A).Inductive evalDet_repeat(A : Set)(P : A -> bool)(c : Comp A)(s : Blist) : comp_answer A -> Prop :=
  | evalDet_repeat_done : forall a s',
    evalDet_repeat_steps P (cs_more c s) (cs_done a s') ->
    evalDet_repeat P c s (ca_done a)
  | evalDet_repeat_eof :
    evalDet_repeat_steps P (cs_more c s) (@cs_eof A) ->
    evalDet_repeat P c s (@ca_eof A).Inductive evalDet_repeat(A : Set)(P : A -> bool)(c : Comp A)(s : Blist) : comp_answer A -> Prop :=
  | evalDet_repeat_done : forall a s',
    evalDet_repeat_steps P (cs_more c s) (cs_done a s') ->
    evalDet_repeat P c s (ca_done a)
  | evalDet_repeat_eof :
    evalDet_repeat_steps P (cs_more c s) (@cs_eof A) ->
    evalDet_repeat P c s (@ca_eof A).

(* Specifications: *)
Lemma list_skipn_strong_ind_h : forall (A : Type) l (P : list A -> Prop) , P nil -> (forall x, (forall n, n > 0 -> P (skipn n x)) -> P x) -> (forall n, P (skipn n l)).
Lemma list_skipn_strong_ind : forall (A : Type) l (P : list A -> Prop) , P nil -> (forall x, (forall n, n > 0 -> P (skipn n x)) -> P x) -> P l.
Lemma evalDet_step_nil_inv : forall (A : Set)(c : Comp A)(a1 a2 : A) s2, evalDet_step c nil = (cs_done a2 s2) -> In a1 (getSupport c) -> a1 = a2.
Lemma evalDet_step_done_nil_inv : forall (A : Set)(c : Comp A) a ls, evalDet_step c nil = (cs_done a ls) -> ls = nil.
Lemma evalDet_step_more_nil_inv : forall (A : Set)(c c' : Comp A) ls, evalDet_step c nil = (cs_more c' ls) -> ls = nil.
Lemma evalDet_step_done_support_singleton : forall (A : Set)(c : Comp A) s a, evalDet_step c s = cs_done a s -> getSupport c = (a :: nil).
Lemma getUnique_NoDup_eq : forall (A : Set)(eqd : eq_dec A)(ls : list A), NoDup ls -> getUnique ls eqd = ls.
Lemma getUnique_Permutation : forall (A : Set)(eqd1 eqd2 : eq_dec A)(ls1 ls2 : list A), Permutation ls1 ls2 -> Permutation (getUnique ls1 eqd1) (getUnique ls2 eqd2).
Lemma flatten_Permutation : forall (A : Type)(ls1 ls2 : list (list A)), Permutation ls1 ls2 -> Permutation (flatten ls1) (flatten ls2).
Lemma to_list_nil_inv : forall (A : Type)(n : nat)(v : Vector.t A n), Vector.to_list v = nil -> n = O.
Lemma app_second_eq : forall (A : Type) (ls2 ls1 ls3 : list A), ls1 = ls2 ++ ls3 -> length ls1 = length ls3 -> ls1 = ls3 /\ ls2 = nil.
Lemma shiftOut_same_inv : forall s n v, shiftOut s n = Some (v, s) -> n = O.
Lemma filter_Permutation : forall (A : Set)(ls1 ls2 : list A)(P : A -> bool), Permutation ls1 ls2 -> Permutation (filter P ls1) (filter P ls2).
Lemma evalDet_step_more_support_preserved : forall (A : Set)(c c' : Comp A) s, evalDet_step c s = (cs_more c' s) -> Permutation (getSupport c) (getSupport c').
Lemma evalDet_steps_nil_eq_h : forall (A : Set)(x y : comp_state A), evalDet_steps x y -> forall (c : Comp A)(a1 a2 : A) s2, x = (cs_more c nil) -> y = (cs_done a2 s2) -> In a1 (getSupport c) -> a1 = a2.
Lemma evalDet_steps_nil_eq : forall (A : Set)(c : Comp A)(a1 a2 : A) s2, evalDet_steps (cs_more c nil) (cs_done a2 s2) -> In a1 (getSupport c) -> a1 = a2.
Lemma evalDet_step_done_val_eq : forall (A : Set)(c : Comp A)(a1 a2 : A) s1 s2, evalDet_step c s1 = (cs_done a2 s2) -> In a1 (getSupport c) -> a1 = a2.
Lemma evalDet_step_done_ls_eq : forall (A : Set)(c : Comp A)(a2 : A) s1 s2, evalDet_step c s1 = (cs_done a2 s2) -> s1 = s2.
Lemma shiftOut_skipn : forall n (v : Bvector n) s s', shiftOut s n = Some (v, s') -> s' = skipn n s.
Lemma evalDet_step_more_skipn_eq : forall (A : Set)(c c' : Comp A)(a1 : A) s1 s2, evalDet_step c s1 = (cs_more c' s2) -> In a1 (getSupport c) -> (s1 = s2 \/ (exists n, n > 0 /\ s2 = skipn n s1)).
Lemma evalDet_step_done_skipn : forall (A : Set)(c : Comp A) s a s', evalDet_step c s = (cs_done a s') -> exists n, s' = skipn n s.
Lemma skipn_sum : forall (A : Type)(n2 n1 : nat)(ls : list A), skipn n1 (skipn n2 ls) = skipn (n2 + n1) ls.
Lemma evalDet_step_more_skipn : forall (A : Set)(c c' : Comp A) s s', evalDet_step c s = (cs_more c' s') -> exists n, s' = skipn n s.
Lemma evalDet_steps_done_skipn_h : forall (A : Set)(x y : comp_state A), evalDet_steps x y -> forall (c : Comp A) s a s', x = (cs_more c s) -> y = (cs_done a s') -> exists n, s' = skipn n s.
Lemma evalDet_steps_done_skipn : forall (A : Set)(c : Comp A) s a s', evalDet_steps (cs_more c s) (cs_done a s') -> exists n, s' = skipn n s.
Lemma evalDet_steps_skipn_h : forall (A : Set) a1 (x y : comp_state A), evalDet_steps x y -> forall (c : Comp A)(a2 : A) s1 s2, x = (cs_more c s1) -> y = (cs_done a2 s2) -> In a1 (getSupport c) -> (a1 = a2 \/ (exists n, n > 0 /\ s2 = skipn n s1)).
Lemma evalDet_steps_skipn : forall (A : Set)(c : Comp A)(a1 a2 : A) s1 s2, evalDet_steps (cs_more c s1) (cs_done a2 s2) -> In a1 (getSupport c) -> (a1 = a2 \/ (exists n, n > 0 /\ s2 = skipn n s1)).
Lemma evalDet_repeat_steps_dec : forall (s : Blist)(A : Set)(c : Comp A)(P : A -> bool), (exists a, In a (getSupport c) /\ P a = true) -> (forall s', (exists a s'', evalDet_steps (cs_more c s') (cs_done a s'')) \/ evalDet_steps (cs_more c s') (@cs_eof A)) -> exists y, evalDet_repeat_steps P (cs_more c s) y.
Lemma evalDet_repeat_steps_done_inv_h : forall (A : Set)(P : A -> bool) x y, evalDet_repeat_steps P x y -> forall c s, x = (cs_more c s) -> evalDet_steps (cs_more (Repeat c P) s) y.
Lemma evalDet_repeat_steps_done_inv : forall (A : Set)(c : Comp A)(P : A -> bool) s y, evalDet_repeat_steps P (cs_more c s) y -> evalDet_steps (cs_more (Repeat c P) s) y.
Lemma evalDet_repeat_steps_more_inv_h : forall (A : Set)(x y : comp_state A) P, evalDet_repeat_steps P x y -> forall (c: Comp A)(P : A -> bool) s, y = (cs_more c s) -> False.
Lemma evalDet_repeat_steps_more_inv : forall (A : Set) x (c : Comp A)(P : A -> bool) s, evalDet_repeat_steps P x (cs_more c s) -> False.
Lemma evalDet_steps_dec : forall (A : Set)(c : Comp A), well_formed_comp c -> forall s, (exists a s', evalDet_steps (cs_more c s) (cs_done a s')) \/ (evalDet_steps (cs_more c s) (@cs_eof A)).
Lemma evalDet_dec : forall (A : Set)(c : Comp A)(s : Blist), well_formed_comp c -> (exists a, evalDet c s (ca_done a)) \/ (evalDet c s (@ca_eof A)).
Lemma evalDet_step_app_done_eq : forall (A : Set)(c : Comp A) s s' s'' a, evalDet_step c s = (cs_done a s'') -> evalDet_step c (s ++ s') = (cs_done a (s'' ++ s')).
Lemma evalDet_step_app_more_eq : forall (A : Set)(c c': Comp A) s s' s'', evalDet_step c s = (cs_more c' s'') -> evalDet_step c (s ++ s') = (cs_more c' (s'' ++ s')).
Lemma evalDet_steps_app_eq_h : forall (A : Set)(x y : comp_state A), evalDet_steps x y -> forall (c : Comp A) s s' s'' a, x = (cs_more c s) -> y = (cs_done a s'') -> evalDet_steps (cs_more c (s ++ s')) (cs_done a (s'' ++ s')).
Lemma evalDet_steps_app_eq : forall (A : Set)(c : Comp A) s s' s'' a, evalDet_steps (cs_more c s) (cs_done a s'') -> evalDet_steps (cs_more c (s ++ s')) (cs_done a (s'' ++ s')).
Lemma evalDet_app_eq : forall (A : Set)(c : Comp A) s s' a, evalDet c s (ca_done a) -> evalDet c (s ++ s') (ca_done a).
Lemma evalDet_steps_done_nil_inv_h : forall (A : Set)(x y : comp_state A), evalDet_steps x y -> forall (c : Comp A) a ls, x = (cs_more c nil) -> y = (cs_done a ls) -> ls = nil.
Lemma evalDet_steps_done_nil_inv : forall (A : Set)(c : Comp A) a ls, evalDet_steps (cs_more c nil) (cs_done a ls) -> ls = nil.
Lemma app_eq_nil_inv : forall (A : Set)(ls2 ls1 ls3 : list A), ls1 = ls2 ++ ls3 -> length ls1 = length ls2 -> ls3 = nil.
Lemma evalDet_steps_repeat_done_inv_h : forall (A : Set)(x y : comp_state A), evalDet_steps x y -> forall (P : A -> bool)(c : Comp A) s a s', evalDet_steps x (cs_more (Repeat c P) s) -> y = (cs_done a s') -> evalDet_repeat_steps P (cs_more c s) (cs_done a s').
Lemma evalDet_steps_repeat_done_inv : forall (A : Set)(P : A -> bool)(c : Comp A) s a s', evalDet_steps (cs_more (Repeat c P) s) (cs_done a s') -> evalDet_repeat_steps P (cs_more c s) (cs_done a s').
Lemma evalDet_steps_repeat_eof_inv_h : forall (A : Set)(x y : comp_state A), evalDet_steps x y -> forall (P : A -> bool)(c : Comp A) s, evalDet_steps x (cs_more (Repeat c P) s) -> y = (cs_eof A) -> evalDet_repeat_steps P (cs_more c s) (cs_eof A).
Lemma evalDet_steps_repeat_eof_inv : forall (A : Set)(P : A -> bool)(c : Comp A) s, evalDet_steps (cs_more (Repeat c P) s) (cs_eof A)-> evalDet_repeat_steps P (cs_more c s) (cs_eof A).
Lemma evalDet_repeat_steps_nil_inv_h : forall (A : Set) P (x y : comp_state A), evalDet_repeat_steps P x y -> forall (P : A -> bool) c a ls', x = (cs_more c nil) -> y = (cs_done a ls') -> ls' = nil.
Lemma evalDet_repeat_steps_nil_inv : forall (A : Set)(P : A -> bool) c a ls', evalDet_repeat_steps P (cs_more c nil) (cs_done a ls') -> ls' = nil.
Lemma evalDet_repeat_steps_app_nil_h : forall (A : Set) P (x y : comp_state A), evalDet_repeat_steps P x y -> forall c ls1 ls2 b a, x = (cs_more c ls1) -> y = (cs_eof A) -> evalDet_repeat_steps P (cs_more c (ls1 ++ b :: nil)) (cs_done a ls2)-> (forall s s' b a, evalDet_steps (cs_more c s) (cs_eof A) -> evalDet_steps (cs_more c (s ++ b :: nil)) (cs_done a s') -> s' = nil) -> ls2 = nil.
Lemma evalDet_repeat_steps_app_nil : forall (A : Set)(c : Comp A) P ls1 ls2 b a, evalDet_repeat_steps P (cs_more c ls1) (cs_eof A) -> evalDet_repeat_steps P (cs_more c (ls1 ++ b :: nil)) (cs_done a ls2) -> (forall s s' b a, evalDet_steps (cs_more c s) (cs_eof A) -> evalDet_steps (cs_more c (s ++ b :: nil)) (cs_done a s') -> s' = nil) -> ls2 = nil.
Lemma evalDet_app_nil : forall (A : Set)(c : Comp A), well_formed_comp c -> forall ls1 ls2 b a, evalDet c ls1 (ca_eof A) -> evalDet_steps (cs_more c (ls1 ++ b :: nil)) (cs_done a ls2) -> ls2 = nil.
Lemma evalDet_step_done_inv : forall (A : Set)(c : Comp A) a ls ls', evalDet_step c ls = cs_done a ls' -> exists eqd, c = Ret eqd a.
Lemma evalDet_step_more_sublist : forall (A : Set)(c : Comp A) c' ls ls', evalDet_step c ls = (cs_more c' ls') -> exists ls'', ls = ls'' ++ ls'.
Lemma evalDet_sublist_h : forall (A : Set)(x y : comp_state A), evalDet_steps x y -> forall (c : Comp A) a ls ls' , x = (cs_more c ls) -> y = (cs_done a ls') -> exists ls'', ls = ls'' ++ ls'.
Lemma evalDet_sublist : forall (A : Set)(c : Comp A) a ls ls', evalDet_steps (cs_more c ls) (cs_done a ls') -> exists ls'', ls = ls'' ++ ls'.
Lemma evalDet_nil : forall (A : Set)(c : Comp A) a ls, evalDet_steps (cs_more c nil) (cs_done a ls) -> ls = nil.
Lemma evalDet_left_total : forall (A : Set)(c : Comp A) s, well_formed_comp c -> exists ans, evalDet c s ans.
Lemma evalDet_steps_done_support_singleton_h : forall (A : Set)(x1 x2 : comp_state A), evalDet_steps x1 x2 -> forall (c : Comp A) a s, x1 = (cs_more c nil) -> x2 = (cs_done a s) -> getSupport c = a :: nil.
Lemma evalDet_steps_done_support_singleton : forall (A : Set)(c : Comp A) a s, evalDet_steps (cs_more c nil) (cs_done a s) -> getSupport c = a :: nil.
Lemma evalDet_step_well_formed_comp_preserved : forall (A : Set)(c : Comp A), well_formed_comp c -> forall c' s s', evalDet_step c s = (cs_more c' s') -> well_formed_comp c'.