Inductive datRepeat (A : Set)(f : DistApproxTree A -> Prop)(P : A -> bool) : nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_leaf_None : forall n,
    datRepeat f P n (dat_leaf None) (dat_leaf None)
  | datRepeat_leaf_Some_yes : forall a n,
    P a = true ->
    datRepeat f P n (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_leaf_Some_no : forall a,
    P a = false ->
    datRepeat f P O (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_leaf_Some_repeat : forall a t t' n,
    f t ->
    P a = false ->
    datRepeat f P n t t' ->
    datRepeat f P (S n) (dat_leaf (Some a)) t'
  | datRepeat_internal : forall n t1 t2 t1' t2',
    datRepeat f P n t1 t1' ->
    datRepeat f P n t2 t2' ->
    datRepeat f P n (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat (A : Set)(f : DistApproxTree A -> Prop)(P : A -> bool) : nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_leaf_None : forall n,
    datRepeat f P n (dat_leaf None) (dat_leaf None)
  | datRepeat_leaf_Some_yes : forall a n,
    P a = true ->
    datRepeat f P n (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_leaf_Some_no : forall a,
    P a = false ->
    datRepeat f P O (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_leaf_Some_repeat : forall a t t' n,
    f t ->
    P a = false ->
    datRepeat f P n t t' ->
    datRepeat f P (S n) (dat_leaf (Some a)) t'
  | datRepeat_internal : forall n t1 t2 t1' t2',
    datRepeat f P n t1 t1' ->
    datRepeat f P n t2 t2' ->
    datRepeat f P n (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat (A : Set)(f : DistApproxTree A -> Prop)(P : A -> bool) : nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_leaf_None : forall n,
    datRepeat f P n (dat_leaf None) (dat_leaf None)
  | datRepeat_leaf_Some_yes : forall a n,
    P a = true ->
    datRepeat f P n (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_leaf_Some_no : forall a,
    P a = false ->
    datRepeat f P O (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_leaf_Some_repeat : forall a t t' n,
    f t ->
    P a = false ->
    datRepeat f P n t t' ->
    datRepeat f P (S n) (dat_leaf (Some a)) t'
  | datRepeat_internal : forall n t1 t2 t1' t2',
    datRepeat f P n t1 t1' ->
    datRepeat f P n t2 t2' ->
    datRepeat f P n (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat (A : Set)(f : DistApproxTree A -> Prop)(P : A -> bool) : nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_leaf_None : forall n,
    datRepeat f P n (dat_leaf None) (dat_leaf None)
  | datRepeat_leaf_Some_yes : forall a n,
    P a = true ->
    datRepeat f P n (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_leaf_Some_no : forall a,
    P a = false ->
    datRepeat f P O (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_leaf_Some_repeat : forall a t t' n,
    f t ->
    P a = false ->
    datRepeat f P n t t' ->
    datRepeat f P (S n) (dat_leaf (Some a)) t'
  | datRepeat_internal : forall n t1 t2 t1' t2',
    datRepeat f P n t1 t1' ->
    datRepeat f P n t2 t2' ->
    datRepeat f P n (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat (A : Set)(f : DistApproxTree A -> Prop)(P : A -> bool) : nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_leaf_None : forall n,
    datRepeat f P n (dat_leaf None) (dat_leaf None)
  | datRepeat_leaf_Some_yes : forall a n,
    P a = true ->
    datRepeat f P n (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_leaf_Some_no : forall a,
    P a = false ->
    datRepeat f P O (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_leaf_Some_repeat : forall a t t' n,
    f t ->
    P a = false ->
    datRepeat f P n t t' ->
    datRepeat f P (S n) (dat_leaf (Some a)) t'
  | datRepeat_internal : forall n t1 t2 t1' t2',
    datRepeat f P n t1 t1' ->
    datRepeat f P n t2 t2' ->
    datRepeat f P n (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat (A : Set)(f : DistApproxTree A -> Prop)(P : A -> bool) : nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_leaf_None : forall n,
    datRepeat f P n (dat_leaf None) (dat_leaf None)
  | datRepeat_leaf_Some_yes : forall a n,
    P a = true ->
    datRepeat f P n (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_leaf_Some_no : forall a,
    P a = false ->
    datRepeat f P O (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_leaf_Some_repeat : forall a t t' n,
    f t ->
    P a = false ->
    datRepeat f P n t t' ->
    datRepeat f P (S n) (dat_leaf (Some a)) t'
  | datRepeat_internal : forall n t1 t2 t1' t2',
    datRepeat f P n t1 t1' ->
    datRepeat f P n t2 t2' ->
    datRepeat f P n (dat_internal t1 t2) (dat_internal t1' t2').Definition dat_correct_repeat2(A : Set)(c : Comp A)(P : A -> bool)(n : nat)(t : DistApproxTree A) :=
exists t1 : DistApproxTree A,
  dat_correct c n t1 /\
  datRepeat (dat_correct c n) P n t1 t.

(* Specifications: *)
Lemma datRepeat_left_total : forall n (A : Set)(eqd : eq_dec A)(t : DistApproxTree A)(f : DistApproxTree A -> Prop) P, (exists b : DistApproxTree A, f b) -> exists t', datRepeat f P n t t'.
Lemma dat_exists_repeat2 : forall (A : Set)(c : Comp A)(P : A -> bool)(n : nat), well_formed_comp c -> exists t : DistApproxTree A, dat_correct_repeat2 c P n t.