Section ListHybrid.
Variable A B C S_A : Set.
Hypothesis eqdb : EqDec B.
Variable defA : A.
Variable A1 : Comp (list A * S_A).
Variable A2 : S_A -> A -> Comp B.
Variable A2' :  S_A -> A -> Comp B.
Variable A3 : S_A -> list B -> Comp C.
Hypothesis A1_wf : well_formed_comp A1.
Hypothesis A2_wf :  forall x y, well_formed_comp (A2 x y).
Hypothesis A2'_wf : forall x y, well_formed_comp (A2' x y).
Variable numA : nat.
Hypothesis numA_correct :
forall lsa s,
In (lsa, s) (getSupport A1) ->
length lsa = numA.
Definition LH_G0  :=
[lsa, s_A] <-$2 A1;
lsb <-$ compMap _ (A2 s_A) lsa;
A3 s_A lsb.
Definition LH_G1 :=
[lsa, s_A] <-$2 A1;
lsb <-$ compMap _ (A2' s_A) lsa;
A3 s_A lsb.
Definition LH_Gn n :=
[lsa, s_A] <-$2 A1;
lsa1 <- firstn n lsa;
lsa2 <- skipn n lsa;
lsb1 <-$ compMap _ (A2' s_A) lsa1;
lsb2 <-$ compMap _ (A2 s_A) lsa2;
A3 s_A (lsb1 ++ lsb2).
Definition LH_G_0  n :=
[lsa, s_A] <-$2 A1;
lsa1 <- firstn n lsa;
a <- nth n lsa defA;
lsa2 <- skipn (S n) lsa;
lsb1 <-$ compMap _ (A2' s_A) lsa1;
b <-$ A2 s_A a;
lsb2 <-$ compMap _ (A2 s_A) lsa2;
A3 s_A (lsb1 ++ (b :: lsb2)).
Definition LH_G_1  n :=
[lsa, s_A] <-$2 A1;
lsa1 <- firstn n lsa;
a <- nth n lsa defA;
lsa2 <- skipn (S n) lsa;
lsb1 <-$ compMap _ (A2' s_A) lsa1;
b <-$ A2' s_A a;
lsb2 <-$ compMap _ (A2 s_A) lsa2;
A3 s_A (lsb1 ++ (b :: lsb2)).
Variable F : nat -> Rat.
Local Opaque evalDist.
induction x; intuition; simpl in *.
rewrite plus_0_r.
eapply leRat_trans.
eapply eqRat_impl_leRat.
rewrite <- ratIdentityIndiscernables.
intuition.
eapply rat0_le_all.
eapply leRat_trans.
eapply ratDistance_le_trans.
eapply H.
assert (n + S x = S n + x)%nat.
omega.
rewrite H0.
clear H0.
eapply IHx.
rewrite map_app.
simpl.
(* eapply eqRat_impl_leRat. rewrite ratS_num. rewrite ratMult_distrib_r. eapply ratAdd_eqRat_compat; intuition. symmetry. eapply ratMult_1_l. *)
(* 1 subgoal, subgoal 1 (ID 390) *)
(*   A, B, C, S_A : Set *)
(*   eqdb : EqDec B *)
(*   defA : A *)
(*   A1 : Comp (list A * S_A) *)
(*   A2, A2' : S_A -> A -> Comp B *)
(*   A3 : S_A -> list B -> Comp C *)
(*   A1_wf : well_formed_comp A1 *)
(*   A2_wf : forall (x : S_A) (y : A), well_formed_comp (A2 x y) *)
(*   A2'_wf : forall (x : S_A) (y : A), well_formed_comp (A2' x y) *)
(*   numA : nat *)
(*   numA_correct : forall (lsa : list A) (s : S_A), *)
(*                  In (lsa, s) (getSupport A1) -> length lsa = numA *)
(*   F : nat -> Rat *)
(*   H : forall (n : nat) (c : C), *)
(*       | evalDist (LH_Gn n) c - evalDist (LH_Gn (S n)) c | <= F n *)
(*   x : nat *)
(*   IHx : forall (n : nat) (c : C), *)
(*         | evalDist (LH_Gn n) c - evalDist (LH_Gn (n + x)) c | <= *)
(*         sumList (map (Init.Nat.add n) (allNatsLt x)) F *)
(*   n : nat *)
(*   c : C *)
(*   ============================ *)
(*   F n + sumList (map (fun m : nat => S (n + m)) (allNatsLt x)) F <= *)
(*   sumList (map (Init.Nat.add n) (allNatsLt x) ++ (n + x)%nat :: nil) F *)
(* (dependent evars: (printing disabled) ) *)
Admitted.
induction ls; intuition; simpl in *.
destruct n; simpl in *; trivial.
destruct n; simpl in *.
omega.
eapply IHls.
omega.
Qed.

Theorem LH_Gn_0_equiv :
forall (n : nat) c,
n < numA ->
evalDist (LH_Gn n) c == evalDist (LH_G_0 n) c.