Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proof of L'Hopital rule #1371

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG_UNRELEASED.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
`locally_compact_completely_regular`, and
`completely_regular_regular`.

- in file `realfun.v`,
+ new lemmas `cauchy_MVT`,
`lhopital_right`, and
`lhopital_left`.

### Changed

- in file `normedtype.v`,
Expand Down
239 changes: 239 additions & 0 deletions theories/realfun.v
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ From HB Require Import structures.
(* lime_sup f a/lime_inf f a == limit sup/inferior of the extended real- *)
(* valued function f at point a *)
(* ``` *)
(* cauchy_MVT == Cauchy's mean value theorem *)
(* lhopital_right == L'Hopital rule (limit taken on the right) *)
(* lhopital_left == L'Hopital rule (limit taken on the left) *)
(* *)
(******************************************************************************)

Expand Down Expand Up @@ -2544,3 +2547,239 @@ apply/continuous_within_itvP => //; split.
Qed.

End variation_continuity.

Section Cauchy_MVT.
Context {R : realType}.
Variables (f df g dg : R -> R) (a b c : R).
Hypothesis ab : a < b.
Hypotheses (cf : {within `[a, b], continuous f})
(cg : {within `[a, b], continuous g}).
Hypotheses (fdf : forall x, x \in `]a, b[%R -> is_derive x 1 f (df x))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we extend the predicate derivable_oo_continuous_bnd to include an option for an explicit derivative as an argument (E.G. derivable_oo_continuous_bnd_with f df x y)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gave it a try, but couldn't extend quickly, so perhaps something to extend separately for a different PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I have no problem with that. Happy to deal with it later.

(gdg : forall x, x \in `]a, b[%R -> is_derive x 1 g (dg x)).
Hypotheses (dg0 : forall x, x \in `]a, b[%R -> dg x != 0).

Lemma differentiable_subr_neq0 :
g b - g a != 0.
Proof.
have [r] := MVT ab gdg cg; rewrite in_itv/= => /andP[ar rb] dgg.
by rewrite dgg mulf_neq0 ?dg0 ?in_itv/= ?ar//; rewrite subr_eq0 gt_eqF.
Qed.

Lemma cauchy_MVT :
exists2 c, c \in `]a, b[%R & df c / dg c = (f b - f a) / (g b - g a).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like callers will need to know that g b - g a != 0. We might as well deduplicate that a bit. I would recommend either an auxiliary lemma that for any g, a and b, {in ]a,b[, dg x != 0 -> g b - g a != 0. Or maybe put a g b - g a != 0 as an extra clause in the result of cauchy_MVT

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, as a separate lemma instead of inside the proof, but unsure if you perhaps meant outside of the MVT Cauchy section (so without all of its assumptions?)

Also I'm a bit unsure of what the naming convention would be for that one, so happy to rename it to something proper.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me. I don't have any idea for naming here, so I'd say it's fine for now.

Proof.
have [r] := MVT ab gdg cg; rewrite in_itv/= => /andP[ar rb] dgg.
pose h (x : R) := f x - ((f b - f a) / (g b - g a)) * g x.
have hder x : x \in `]a, b[%R -> derivable h x 1.
move=> xab; apply: derivableB => /=.
exact: (@ex_derive _ _ _ _ _ _ _ (fdf xab)).
by apply: derivableM => //; exact: (@ex_derive _ _ _ _ _ _ _ (gdg xab)).
have ch : {within `[a, b], continuous h}.
rewrite continuous_subspace_in => x xab.
by apply: cvgB; [exact: cf|apply: cvgM; [exact: cvg_cst|exact: cg]].
have /(Rolle ab hder ch)[x xab derh] : h a = h b.
rewrite /h; apply/eqP; rewrite subr_eq eq_sym -addrA eq_sym addrC -subr_eq.
rewrite -mulrN -mulrDr -(addrC (g a)) -[X in _ * X]opprB mulrN -mulrA.
rewrite mulVf//.
by rewrite mulr1 opprB.
by rewrite differentiable_subr_neq0.
pose dh (x : R) := df x - (f b - f a) / (g b - g a) * dg x.
have his_der y : y \in `]a, b[%R -> is_derive x 1 h (dh x).
by move=> yab; apply: is_deriveB; [exact: fdf|apply: is_deriveZ; exact: gdg].
exists x => //.
have := @derive_val _ R _ _ _ _ _ (his_der _ xab).
have -> := @derive_val _ R _ _ _ _ _ derh.
move=> /eqP; rewrite eq_sym subr_eq add0r => /eqP ->.
by rewrite -mulrA divff ?mulr1//; exact: dg0.
Qed.

End Cauchy_MVT.

Section lhopital.
Context {R : realType}.
Variables (f df g dg : R -> R) (a : R) (U : set R) (Ua : nbhs a U).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As usual, a question about boundary conditions. I'm a bit surprised to see we require f to be derivable in a full neighborhood of a. But then only take the right/left limit. Instead I would expect to see either a^'- U or a^'+U depending on the direction of the limit. Will the theorem still go through with that weakening?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch - I think this should go through, but changes are a bit more time-consuming than I expected so still in progress, should be done sometime next week.

Hypotheses (fdf : forall x, x \in U -> is_derive x 1 f (df x))
(gdg : forall x, x \in U -> is_derive x 1 g (dg x)).
Hypotheses (fa0 : f a = 0) (ga0 : g a = 0)
(cdg : \forall x \near a^', dg x != 0).

Lemma lhopital_right (l : R) :
df x / dg x @[x --> a^'+] --> l -> f x / g x @[x --> a^'+] --> l.
Proof.
case: cdg => r/= r0 cdg'.
move: Ua; rewrite filter_of_nearI => -[D /= D0 aDU].
near a^'+ => b.
have abf x : x \in `]a, b[%R -> {within `[a, x], continuous f}.
rewrite in_itv/= => /andP[ax xb].
apply: derivable_within_continuous => y; rewrite in_itv/= => /andP[ay yx].
apply: ex_derive.
apply: fdf.
rewrite inE; apply: aDU => /=.
rewrite ler0_norm? subr_le0//.
rewrite opprD opprK addrC ltrBlDr (le_lt_trans yx)// (lt_trans xb)//.
near: b; apply: nbhs_right_lt.
by rewrite ltrDr.
have abg x : x \in `]a, b[%R -> {within `[a, x], continuous g}.
rewrite in_itv/= => /andP[ax xb].
apply: derivable_within_continuous => y; rewrite in_itv/= => /andP[ay yx].
apply: ex_derive.
apply: gdg.
rewrite inE; apply: aDU => /=.
rewrite ler0_norm? subr_le0//.
rewrite opprD opprK addrC ltrBlDr (le_lt_trans yx)// (lt_trans xb)//.
near: b; apply: nbhs_right_lt.
by rewrite ltrDr.
have fdf' y : y \in `]a, b[%R -> is_derive y 1 f (df y).
rewrite in_itv/= => /andP[ay yb]; apply: fdf.
rewrite inE; apply: aDU => /=.
rewrite ltr0_norm ?subr_lt0//.
rewrite opprD opprK addrC ltrBlDr (lt_le_trans yb)//.
near: b; apply: nbhs_right_le.
by rewrite ltrDr.
have gdg' y : y \in `]a, b[%R -> is_derive y 1 g (dg y).
rewrite in_itv/= => /andP[ay yb]; apply: gdg.
rewrite inE; apply: aDU => /=.
rewrite ltr0_norm ?subr_lt0//.
rewrite opprD opprK addrC ltrBlDr (lt_le_trans yb)//.
near: b; apply: nbhs_right_le.
by rewrite ltrDr.
have {}dg0 y : y \in `]a, b[%R -> dg y != 0.
rewrite in_itv/= => /andP[ay yb].
apply: (cdg' y) => /=; last by rewrite gt_eqF.
rewrite ltr0_norm; last by rewrite subr_lt0.
rewrite opprB ltrBlDl (lt_trans yb)//.
near: b; apply: nbhs_right_lt.
by rewrite ltrDl.
move=> fgal.
have L : \forall x \near a^'+,
exists2 c, c \in `]a, x[%R & df c / dg c = f x / g x.
near=> x.
have /andP[ax xb] : a < x < b by exact/andP.
have {}fdf' y : y \in `]a, x[%R -> is_derive y 1 f (df y).
rewrite !in_itv/= => /andP[ay yx].
by apply: fdf'; rewrite in_itv/= ay/= (lt_trans yx).
have {}gdg' y : y \in `]a, x[%R -> is_derive y 1 g (dg y).
rewrite !in_itv/= => /andP[ay yx].
by apply: gdg'; rewrite in_itv/= ay/= (lt_trans yx).
have {}dg0 y : y \in `]a, x[%R -> dg y != 0.
rewrite in_itv/= => /andP[ya yx].
by apply: dg0; rewrite in_itv/= ya/= (lt_trans yx).
have {}axf : {within `[a, x], continuous f}.
rewrite continuous_subspace_in => y; rewrite inE/= in_itv/= => /andP[ay yx].
by apply: abf; rewrite in_itv/= xb andbT.
have {}axg : {within `[a, x], continuous g}.
rewrite continuous_subspace_in => y; rewrite inE/= in_itv/= => /andP[ay yx].
by apply: abg; rewrite in_itv/= xb andbT.
have := @cauchy_MVT _ f df g dg _ _ ax axf axg fdf' gdg' dg0.
by rewrite fa0 ga0 2!subr0.
apply/cvgrPdist_le => /= e e0.
move/cvgrPdist_le : fgal.
move=> /(_ _ e0)[r'/= r'0 fagl].
case: L => d /= d0 L.
near=> t.
have /= := L t.
have atd : `|a - t| < d.
rewrite ltr0_norm; last by rewrite subr_lt0.
rewrite opprB ltrBlDl.
near: t; apply: nbhs_right_lt.
by rewrite ltrDl.
have at_ : a < t by [].
move=> /(_ atd)/(_ at_)[c]; rewrite in_itv/= => /andP[ac ct <-].
apply: fagl => //=.
rewrite ltr0_norm; last by rewrite subr_lt0.
rewrite opprB ltrBlDl (lt_trans ct)//.
near: t; apply: nbhs_right_lt.
by rewrite ltrDl.
Unshelve. all: by end_near. Qed.

Lemma lhopital_left (l : R) :
df x / dg x @[x --> a^'-] --> l -> f x / g x @[x --> a^'-] --> l.
Proof.
case: cdg => r/= r0 cdg'.
move: Ua; rewrite filter_of_nearI => -[D /= D0 aDU].
near a^'- => b.
have baf x : x \in `]b, a[%R -> {within `[x, a], continuous f}.
rewrite in_itv/= => /andP[bx xa].
apply: derivable_within_continuous => y; rewrite in_itv/= => /andP[xy ya].
apply: ex_derive.
apply: fdf.
rewrite inE; apply: aDU => /=.
rewrite ger0_norm ?subr_ge0//.
rewrite ltrBlDr -ltrBlDl (lt_le_trans _ xy)// (le_lt_trans _ bx)//.
near: b; apply: nbhs_left_ge.
by rewrite ltrBlDl ltrDr.
have bag x : x \in `]b, a[%R -> {within `[x, a], continuous g}.
rewrite in_itv/= => /andP[bx xa].
apply: derivable_within_continuous => y; rewrite in_itv/= => /andP[xy ya].
apply: ex_derive.
apply: gdg.
rewrite inE; apply: aDU => /=.
rewrite ger0_norm ?subr_ge0//.
rewrite ltrBlDr -ltrBlDl (lt_le_trans _ xy)// (lt_trans _ bx)//.
near: b; apply: nbhs_left_gt.
by rewrite ltrBlDl ltrDr.
have fdf' y : y \in `]b, a[%R -> is_derive y 1 f (df y).
rewrite in_itv/= => /andP[by_ ya]; apply: fdf.
rewrite inE.
apply: aDU => /=.
rewrite gtr0_norm ?subr_gt0//.
rewrite ltrBlDl -ltrBlDr (le_lt_trans _ by_)//.
near: b; apply: nbhs_left_ge.
by rewrite ltrBlDr ltrDl.
have gdg' y : y \in `]b, a[%R -> is_derive y 1 g (dg y).
rewrite in_itv/= => /andP[by_ ya]; apply: gdg.
rewrite inE; apply: aDU => /=.
rewrite gtr0_norm ?subr_gt0//.
rewrite ltrBlDl -ltrBlDr (le_lt_trans _ by_)//.
near: b; apply: nbhs_left_ge.
by rewrite ltrBlDr ltrDl.
have {}dg0 y : y \in `]b, a[%R -> dg y != 0.
rewrite in_itv/= => /andP[by_ ya].
apply: (cdg' y) => /=; last by rewrite lt_eqF.
rewrite gtr0_norm; last by rewrite subr_gt0.
rewrite ltrBlDr -ltrBlDl (lt_trans _ by_)//.
near: b; apply: nbhs_left_gt.
by rewrite ltrBlDl ltrDr.
move=> fgal.
have L : \forall x \near a^'-,
exists2 c, c \in `]x, a[%R & df c / dg c = f x / g x.
near=> x.
have /andP[bx xa] : b < x < a by exact/andP.
have {}fdf' y : y \in `]x, a[%R -> is_derive y 1 f (df y).
rewrite in_itv/= => /andP[xy ya].
by apply: fdf'; rewrite in_itv/= ya andbT (lt_trans bx).
have {}gdg' y : y \in `]x, a[%R -> is_derive y 1 g (dg y).
rewrite in_itv/= => /andP[xy ya].
by apply: gdg'; rewrite in_itv/= ya andbT (lt_trans _ xy).
have {}dg0 y : y \in `]x, a[%R -> dg y != 0.
rewrite in_itv/= => /andP[xy ya].
by apply: dg0; rewrite in_itv/= ya andbT (lt_trans bx).
have {}xaf : {within `[x, a], continuous f}.
rewrite continuous_subspace_in => y; rewrite inE/= in_itv/= => /andP[xy ya].
by apply: baf; rewrite in_itv/= bx.
have {}xag : {within `[x, a], continuous g}.
rewrite continuous_subspace_in => y; rewrite inE/= in_itv/= => /andP[xy ya].
by apply: bag; rewrite in_itv/= bx.
have := @cauchy_MVT _ f df g dg _ _ xa xaf xag fdf' gdg' dg0.
by rewrite fa0 ga0 !sub0r divrN mulNr opprK.
apply/cvgrPdist_le => /= e e0.
move/cvgrPdist_le : fgal.
move=> /(_ _ e0)[r'/= r'0 fagl].
case: L => d /= d0 L.
near=> t.
have /= := L t.
have atd : `|a - t| < d.
rewrite gtr0_norm; last by rewrite subr_gt0.
rewrite ltrBlDr -ltrBlDl.
near: t; apply: nbhs_left_gt.
by rewrite ltrBlDl ltrDr.
have ta : t < a by [].
move=> /(_ atd)/(_ ta)[c]; rewrite in_itv/= => /andP[tc ca <-].
apply: fagl => //=.
rewrite gtr0_norm; last by rewrite subr_gt0.
rewrite ltrBlDr -ltrBlDl (lt_trans _ tc)//.
near: t; apply: nbhs_left_gt.
by rewrite ltrBlDl ltrDr.
Unshelve. all: by end_near. Qed.

End lhopital.