Inductive datRepeat_depth (A : Set)(f : nat -> DistApproxTree A -> Prop)(P : A -> bool) : nat -> nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_depth_leaf_None : forall n depth,
    datRepeat_depth f P n depth (dat_leaf None) (dat_leaf None)
  | datRepeat_depth_leaf_Some_yes : forall a n depth,
    P a = true ->
    datRepeat_depth f P n depth (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_depth_leaf_Some_no : forall a depth,
    P a = false ->
    datRepeat_depth f P O depth (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_depth_leaf_Some_repeat : forall a t t' n depth,
    P a = false ->
    f depth t ->
    datRepeat_depth f P n depth t t' ->
    datRepeat_depth f P (S n) depth (dat_leaf (Some a)) t'
  | datRepeat_depth_internal : forall n depth t1 t2 t1' t2',
    datRepeat_depth f P n depth t1 t1' ->
    datRepeat_depth f P n depth t2 t2' ->
    datRepeat_depth f P n (S depth) (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat_depth (A : Set)(f : nat -> DistApproxTree A -> Prop)(P : A -> bool) : nat -> nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_depth_leaf_None : forall n depth,
    datRepeat_depth f P n depth (dat_leaf None) (dat_leaf None)
  | datRepeat_depth_leaf_Some_yes : forall a n depth,
    P a = true ->
    datRepeat_depth f P n depth (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_depth_leaf_Some_no : forall a depth,
    P a = false ->
    datRepeat_depth f P O depth (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_depth_leaf_Some_repeat : forall a t t' n depth,
    P a = false ->
    f depth t ->
    datRepeat_depth f P n depth t t' ->
    datRepeat_depth f P (S n) depth (dat_leaf (Some a)) t'
  | datRepeat_depth_internal : forall n depth t1 t2 t1' t2',
    datRepeat_depth f P n depth t1 t1' ->
    datRepeat_depth f P n depth t2 t2' ->
    datRepeat_depth f P n (S depth) (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat_depth (A : Set)(f : nat -> DistApproxTree A -> Prop)(P : A -> bool) : nat -> nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_depth_leaf_None : forall n depth,
    datRepeat_depth f P n depth (dat_leaf None) (dat_leaf None)
  | datRepeat_depth_leaf_Some_yes : forall a n depth,
    P a = true ->
    datRepeat_depth f P n depth (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_depth_leaf_Some_no : forall a depth,
    P a = false ->
    datRepeat_depth f P O depth (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_depth_leaf_Some_repeat : forall a t t' n depth,
    P a = false ->
    f depth t ->
    datRepeat_depth f P n depth t t' ->
    datRepeat_depth f P (S n) depth (dat_leaf (Some a)) t'
  | datRepeat_depth_internal : forall n depth t1 t2 t1' t2',
    datRepeat_depth f P n depth t1 t1' ->
    datRepeat_depth f P n depth t2 t2' ->
    datRepeat_depth f P n (S depth) (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat_depth (A : Set)(f : nat -> DistApproxTree A -> Prop)(P : A -> bool) : nat -> nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_depth_leaf_None : forall n depth,
    datRepeat_depth f P n depth (dat_leaf None) (dat_leaf None)
  | datRepeat_depth_leaf_Some_yes : forall a n depth,
    P a = true ->
    datRepeat_depth f P n depth (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_depth_leaf_Some_no : forall a depth,
    P a = false ->
    datRepeat_depth f P O depth (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_depth_leaf_Some_repeat : forall a t t' n depth,
    P a = false ->
    f depth t ->
    datRepeat_depth f P n depth t t' ->
    datRepeat_depth f P (S n) depth (dat_leaf (Some a)) t'
  | datRepeat_depth_internal : forall n depth t1 t2 t1' t2',
    datRepeat_depth f P n depth t1 t1' ->
    datRepeat_depth f P n depth t2 t2' ->
    datRepeat_depth f P n (S depth) (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat_depth (A : Set)(f : nat -> DistApproxTree A -> Prop)(P : A -> bool) : nat -> nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_depth_leaf_None : forall n depth,
    datRepeat_depth f P n depth (dat_leaf None) (dat_leaf None)
  | datRepeat_depth_leaf_Some_yes : forall a n depth,
    P a = true ->
    datRepeat_depth f P n depth (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_depth_leaf_Some_no : forall a depth,
    P a = false ->
    datRepeat_depth f P O depth (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_depth_leaf_Some_repeat : forall a t t' n depth,
    P a = false ->
    f depth t ->
    datRepeat_depth f P n depth t t' ->
    datRepeat_depth f P (S n) depth (dat_leaf (Some a)) t'
  | datRepeat_depth_internal : forall n depth t1 t2 t1' t2',
    datRepeat_depth f P n depth t1 t1' ->
    datRepeat_depth f P n depth t2 t2' ->
    datRepeat_depth f P n (S depth) (dat_internal t1 t2) (dat_internal t1' t2').Inductive datRepeat_depth (A : Set)(f : nat -> DistApproxTree A -> Prop)(P : A -> bool) : nat -> nat -> DistApproxTree A -> DistApproxTree A -> Prop :=
  | datRepeat_depth_leaf_None : forall n depth,
    datRepeat_depth f P n depth (dat_leaf None) (dat_leaf None)
  | datRepeat_depth_leaf_Some_yes : forall a n depth,
    P a = true ->
    datRepeat_depth f P n depth (dat_leaf (Some a)) (dat_leaf (Some a))
  | datRepeat_depth_leaf_Some_no : forall a depth,
    P a = false ->
    datRepeat_depth f P O depth (dat_leaf (Some a)) (dat_leaf None)
  | datRepeat_depth_leaf_Some_repeat : forall a t t' n depth,
    P a = false ->
    f depth t ->
    datRepeat_depth f P n depth t t' ->
    datRepeat_depth f P (S n) depth (dat_leaf (Some a)) t'
  | datRepeat_depth_internal : forall n depth t1 t2 t1' t2',
    datRepeat_depth f P n depth t1 t1' ->
    datRepeat_depth f P n depth t2 t2' ->
    datRepeat_depth f P n (S depth) (dat_internal t1 t2) (dat_internal t1' t2').Definition dat_correct_repeat(A : Set) (c : Comp A)(P : A -> bool)(n : nat)(t : DistApproxTree A) :=
exists t1 : DistApproxTree A,
  dat_correct c n t1 /\
  datRepeat_depth (dat_correct c) P n n t1 t.

Lemma datRepeat_depth_better: forall (n2 : nat) (A : Set) (t2 t1 t1' : DistApproxTree A)(rel : nat -> DistApproxTree A -> Prop) reps depth (P : A -> bool), datRepeat_depth rel P reps depth t1 t1' -> forall n1 (t2' : DistApproxTree A), reps >= n2 -> datRepeat (rel n1) P n2 t2 t2' -> dat_better t1 t2 -> depth >= n1 * n2 + datDepth t2 -> (forall (n1 n2: nat) (t3 t4 : DistApproxTree A), rel n1 t3 -> rel n2 t4 -> n1 >= n2 -> dat_better t3 t4) -> (forall a, rel 0%nat (dat_leaf (Some a)) -> P a = true) -> (forall n t, rel n t -> datDepth t <= n)%nat -> dat_better t1' t2'.