Section Limit.
Variable A : Set.
Variable eq : A -> A -> Prop.
Hypothesis eq_dec : forall (a1 a2 : A),
{eq a1 a2} + {~eq a1 a2}.
Hypothesis eq_refl : forall (a : A),
eq a a.
Hypothesis eq_symm : forall a1 a2,
eq a1 a2 ->
eq a2 a1.
Variable distance : A -> A -> A.
Hypothesis distance_comm : forall a1 a2,
eq (distance a1 a2) (distance a2 a1).
Variable half : A -> A.
Variable zero : A.
Hypothesis half_nz : forall (a : A),
~eq a zero ->
~eq (half a) zero.
Hypothesis distance_eq_zero : forall (a1 a2 : A),
eq a1 a2 <->
eq (distance a1 a2) zero.
Hypothesis distance_eq_compat : forall a1 a2 a3 a4,
eq a1 a3 ->
eq a2 a4 ->
eq (distance a1 a2) (distance a3 a4).
Variable le : A -> A -> Prop.
Hypothesis le_eq : forall (a1 a2 : A),
eq a1 a2 ->
le a1 a2.
Hypothesis le_trans : forall (a1 a2 a3 : A),
le a1 a2 ->
le a2 a3 ->
le a1 a3.
(* all numbers positive *)
Hypothesis all_pos : forall (a : A),
le zero a.
Hypothesis le_impl_eq : forall (a1 a2 : A),
le a1 a2 ->
le a2 a1 ->
eq a1 a2.
Variable plus : A -> A -> A.
Variable plus_0_eq : forall (a1 a2 : A),
eq a2 zero ->
eq a1 (plus a1 a2).
Variable plus_le_compat : forall a1 a2 a3 a4,
le a1 a2 ->
le a3 a4 ->
le (plus a1 a3) (plus a2 a4).
Hypothesis triangle_inequality : forall (a1 a2 a3 : A),
le (distance a1 a2) (plus (distance a1 a3) (distance a3 a2)).
Hypothesis half_plus : forall (a : A),
eq (plus (half a) (half a)) a.
Hypothesis le_half : forall (a : A),
le a (half a) ->
eq a zero.
intuition.
destruct (eq_dec a zero).
trivial.
exfalso.
specialize (H (half a)).
apply f.
eapply le_half.
apply H.
eapply half_nz.
trivial.
Qed.
Definition left_total(r : nat -> A -> Prop) :=
forall n, exists a, r n a.
Definition functional(r : nat -> A -> Prop) :=
forall n a1 a2,
r n a1 ->
r n a2 ->
eq a1 a2.
Definition inf_limit(f : nat -> A -> Prop)(a : A) :=
forall (epsilon : A),
~eq epsilon zero ->
exists n : nat,
forall (n' : nat),
n' >= n ->
forall a',
f n' a' ->
le (distance a' a) epsilon.
(* Note: if the codomain of the relation is empty (after any point), then we can assign any limit to it. *)
(* We could define inf_limit in terms of inf_limit_2, but inf_limit_2 only shows up in proofs, while inf_limit shows up in top-level definitions. *)
Definition inf_limit_2(f f' : nat -> A -> Prop) :=
forall (epsilon : A),
~eq epsilon zero ->
exists n : nat,
forall (n' : nat),
n' >= n ->
forall a a',
f n' a ->
f' n' a' ->
le (distance a a') epsilon.
intuition.
Abort.
(*  remember half as h. *)
intuition.
unfold inf_limit in *.
intuition.
specialize (H1 (half epsilon)).
specialize (H2 (half epsilon)).
destruct H1.
intuition.
eapply half_nz; eauto.
destruct H2.
intuition.
eapply half_nz; eauto.
destruct (H (max x x0)).
specialize (H1 (max x x0)).
specialize (H2 (max x x0)).
eapply le_trans.
eapply (triangle_inequality _ _ x1).
eapply le_trans.
eapply plus_le_compat.
eapply le_trans.
eapply le_eq.
eapply distance_comm.
eapply H1.
eapply Max.max_lub_l; eauto.
trivial.
eapply H2.
eapply Max.max_lub_r; eauto.
trivial.
eapply le_eq.
eapply half_plus.
Qed.
intuition.
eapply distance_eq_zero.
eapply le_epsilon_zero.
intuition.
eapply limit_eq_h; eauto.
Qed.
unfold inf_limit; intuition.
destruct (H epsilon).
trivial.
exists x.
intuition.
eapply H2.
eapply H3.
eapply H0.
trivial.
Qed.
End Limit.
(* limits for Rat *)
Local Open Scope rat_scope.
Definition rat_inf_limit(f : nat -> Rat -> Prop)(r : Rat) :=
inf_limit eqRat ratDistance rat0 leRat f r.
Definition rat_inf_limit_2(f1 f2 : nat -> Rat -> Prop) :=
inf_limit_2 eqRat ratDistance rat0 leRat f1 f2.
Definition rat_limits_eq :=
limits_eq eq_Rat_dec ratDistance_comm ratHalf ratHalf_ne_0 ratIdentityIndiscernables eqRat_impl_leRat leRat_trans ratAdd ratAdd_leRat_compat ratTriangleInequality ratHalf_add le_ratHalf_0.

Theorem rat_inf_limit_2_trans : forall f1 f2 f3,
rat_inf_limit_2 f1 f2 ->
rat_inf_limit_2 f2 f3 ->
left_total f2 ->
rat_inf_limit_2 f1 f3.