Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
Well-founded relations and natural numbers
Require Import PeanoNat Lt. Local Open Scope nat_scope. Implicit Types m n p : nat. Section Well_founded_Nat. Variable A : Type. Variable f : A -> nat. Definition ltof (a b:A) := f a < f b. Definition gtof (a b:A) := f b > f a.A:Typef:A -> natwell_founded ltofA:Typef:A -> natwell_founded ltofA:Typef:A -> natforall (n : nat) (a : A), f a < n -> Acc ltof aA:Typef:A -> natH:forall (n : nat) (a : A), f a < n -> Acc ltof awell_founded ltofA:Typef:A -> natforall (n : nat) (a : A), f a < n -> Acc ltof aA:Typef:A -> natforall a : A, f a < 0 -> Acc ltof aA:Typef:A -> natn:natIHn:forall a : A, f a < n -> Acc ltof aforall a : A, f a < S n -> Acc ltof aintros; absurd (f a < 0); auto with arith.A:Typef:A -> natforall a : A, f a < 0 -> Acc ltof aA:Typef:A -> natn:natIHn:forall a : A, f a < n -> Acc ltof aforall a : A, f a < S n -> Acc ltof aA:Typef:A -> natn:natIHn:forall a0 : A, f a0 < n -> Acc ltof a0a:AHa:f a < S nAcc ltof aA:Typef:A -> natn:natIHn:forall a0 : A, f a0 < n -> Acc ltof a0a:AHa:f a < S nforall y : A, ltof y a -> Acc ltof yA:Typef:A -> natn:natIHn:forall a0 : A, f a0 < n -> Acc ltof a0a:AHa:f a < S nforall y : A, f y < f a -> Acc ltof yA:Typef:A -> natn:natIHn:forall a0 : A, f a0 < n -> Acc ltof a0a:AHa:f a < S nb:AHb:f b < f aAcc ltof bapply Nat.lt_le_trans with (f a); auto with arith.A:Typef:A -> natn:natIHn:forall a0 : A, f a0 < n -> Acc ltof a0a:AHa:f a < S nb:AHb:f b < f af b < nA:Typef:A -> natH:forall (n : nat) (a : A), f a < n -> Acc ltof awell_founded ltofA:Typef:A -> natH:forall (n : nat) (a0 : A), f a0 < n -> Acc ltof a0a:AAcc ltof aauto with arith. Defined.A:Typef:A -> natH:forall (n : nat) (a0 : A), f a0 < n -> Acc ltof a0a:Af a < S (f a)A:Typef:A -> natwell_founded gtofexact well_founded_ltof. Defined.A:Typef:A -> natwell_founded gtof
It is possible to directly prove the induction principle going
back to primitive recursion on natural numbers (induction_ltof1)
or to use the previous lemmas to extract a program with a fixpoint
(induction_ltof2)
the ML-like program for induction_ltof1 is :
let induction_ltof1 f F a =
let rec indrec n k =
match n with
| O → error
| S m → F k (indrec m)
in indrec (f a + 1) a
the ML-like program for induction_ltof2 is :
let induction_ltof2 F a = indrec a
where rec indrec a = F a indrec;;
let induction_ltof1 f F a =
let rec indrec n k =
match n with
| O → error
| S m → F k (indrec m)
in indrec (f a + 1) a
let induction_ltof2 F a = indrec a
where rec indrec a = F a indrec;;
A:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, ltof y x -> P y) -> P x) -> forall a : A, P aA:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, ltof y x -> P y) -> P x) -> forall a : A, P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xforall a : A, P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xforall (n : nat) (a : A), f a < n -> P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xH:forall (n : nat) (a : A), f a < n -> P aforall a : A, P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xforall (n : nat) (a : A), f a < n -> P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xforall a : A, f a < 0 -> P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xn:natIHn:forall a : A, f a < n -> P aforall a : A, f a < S n -> P aintros; absurd (f a < 0); auto with arith.A:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xforall a : A, f a < 0 -> P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xn:natIHn:forall a : A, f a < n -> P aforall a : A, f a < S n -> P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xn:natIHn:forall a0 : A, f a0 < n -> P a0a:AHa:f a < S nP aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xn:natIHn:forall a0 : A, f a0 < n -> P a0a:AHa:f a < S nforall y : A, ltof y a -> P yA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xn:natIHn:forall a0 : A, f a0 < n -> P a0a:AHa:f a < S nforall y : A, f y < f a -> P yA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xn:natIHn:forall a0 : A, f a0 < n -> P a0a:AHa:f a < S nb:AHb:f b < f aP bapply Nat.lt_le_trans with (f a); auto with arith.A:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xn:natIHn:forall a0 : A, f a0 < n -> P a0a:AHa:f a < S nb:AHb:f b < f af b < nA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xH:forall (n : nat) (a : A), f a < n -> P aforall a : A, P aA:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xH:forall (n : nat) (a0 : A), f a0 < n -> P a0a:AP aauto with arith. Defined.A:Typef:A -> natP:A -> SetF:forall x : A, (forall y : A, ltof y x -> P y) -> P xH:forall (n : nat) (a0 : A), f a0 < n -> P a0a:Af a < S (f a)A:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, gtof y x -> P y) -> P x) -> forall a : A, P aexact induction_ltof1. Defined.A:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, gtof y x -> P y) -> P x) -> forall a : A, P aA:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, ltof y x -> P y) -> P x) -> forall a : A, P aexact (well_founded_induction well_founded_ltof). Defined.A:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, ltof y x -> P y) -> P x) -> forall a : A, P aA:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, gtof y x -> P y) -> P x) -> forall a : A, P aexact induction_ltof2. Defined.A:Typef:A -> natforall P : A -> Set, (forall x : A, (forall y : A, gtof y x -> P y) -> P x) -> forall a : A, P a
If a relation R is compatible with lt i.e. if x R y ⇒ f(x) < f(y)
then R is well-founded.
Variable R : A -> A -> Prop. Hypothesis H_compat : forall x y:A, R x y -> f x < f y.A:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f ywell_founded RA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f ywell_founded RA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yforall (n : nat) (a : A), f a < n -> Acc R aA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yH:forall (n : nat) (a : A), f a < n -> Acc R awell_founded RA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yforall (n : nat) (a : A), f a < n -> Acc R aA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yforall a : A, f a < 0 -> Acc R aA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yn:natIHn:forall a : A, f a < n -> Acc R aforall a : A, f a < S n -> Acc R aintros; absurd (f a < 0); auto with arith.A:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yforall a : A, f a < 0 -> Acc R aA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yn:natIHn:forall a : A, f a < n -> Acc R aforall a : A, f a < S n -> Acc R aA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yn:natIHn:forall a0 : A, f a0 < n -> Acc R a0a:AHa:f a < S nAcc R aA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yn:natIHn:forall a0 : A, f a0 < n -> Acc R a0a:AHa:f a < S nforall y : A, R y a -> Acc R yA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yn:natIHn:forall a0 : A, f a0 < n -> Acc R a0a:AHa:f a < S nb:AHb:R b aAcc R bapply Nat.lt_le_trans with (f a); auto with arith.A:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yn:natIHn:forall a0 : A, f a0 < n -> Acc R a0a:AHa:f a < S nb:AHb:R b af b < nA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yH:forall (n : nat) (a : A), f a < n -> Acc R awell_founded RA:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yH:forall (n : nat) (a0 : A), f a0 < n -> Acc R a0a:AAcc R aauto with arith. Defined. End Well_founded_Nat.A:Typef:A -> natR:A -> A -> PropH_compat:forall x y : A, R x y -> f x < f yH:forall (n : nat) (a0 : A), f a0 < n -> Acc R a0a:Af a < S (f a)well_founded ltexact (well_founded_ltof nat (fun m => m)). Defined.well_founded ltforall (n : nat) (P : nat -> Set), (forall n0 : nat, (forall m : nat, m < n0 -> P m) -> P n0) -> P nexact (fun p P F => induction_ltof1 nat (fun m => m) P F p). Defined.forall (n : nat) (P : nat -> Set), (forall n0 : nat, (forall m : nat, m < n0 -> P m) -> P n0) -> P nforall (n : nat) (P : nat -> Set), (forall n0 : nat, (forall m : nat, m < n0 -> P m) -> P n0) -> P nexact (fun p P F => induction_ltof2 nat (fun m => m) P F p). Defined.forall (n : nat) (P : nat -> Set), (forall n0 : nat, (forall m : nat, m < n0 -> P m) -> P n0) -> P nforall (n : nat) (P : nat -> Prop), (forall n0 : nat, (forall m : nat, m < n0 -> P m) -> P n0) -> P nintro p; intros; elim (lt_wf p); auto with arith. Qed.forall (n : nat) (P : nat -> Prop), (forall n0 : nat, (forall m : nat, m < n0 -> P m) -> P n0) -> P nforall (n : nat) (P : nat -> Set), (forall n0 : nat, (forall m : nat, n0 > m -> P m) -> P n0) -> P nexact lt_wf_rec. Defined.forall (n : nat) (P : nat -> Set), (forall n0 : nat, (forall m : nat, n0 > m -> P m) -> P n0) -> P nProof lt_wf_ind.forall (n : nat) (P : nat -> Prop), (forall n0 : nat, (forall m : nat, n0 > m -> P m) -> P n0) -> P nforall P : nat -> nat -> Set, (forall n m : nat, (forall p q : nat, p < n -> P p q) -> (forall p : nat, p < m -> P n p) -> P n m) -> forall n m : nat, P n mforall P : nat -> nat -> Set, (forall n m : nat, (forall p q : nat, p < n -> P p q) -> (forall p : nat, p < m -> P n p) -> P n m) -> forall n m : nat, P n mintros n H q; pattern q; apply lt_wf_rec; auto with arith. Defined.P:nat -> nat -> SetHrec:forall n m : nat, (forall p0 q : nat, p0 < n -> P p0 q) -> (forall p0 : nat, p0 < m -> P n p0) -> P n mp:natforall n : nat, (forall m : nat, m < n -> forall m0 : nat, P m m0) -> forall m : nat, P n mforall P : nat -> nat -> Prop, (forall n m : nat, (forall p q : nat, p < n -> P p q) -> (forall p : nat, p < m -> P n p) -> P n m) -> forall n m : nat, P n mforall P : nat -> nat -> Prop, (forall n m : nat, (forall p q : nat, p < n -> P p q) -> (forall p : nat, p < m -> P n p) -> P n m) -> forall n m : nat, P n mintros n H q; pattern q; apply lt_wf_ind; auto with arith. Qed. Hint Resolve lt_wf: arith. Hint Resolve well_founded_lt_compat: arith. Section LT_WF_REL. Variable A : Set. Variable R : A -> A -> Prop. (* Relational form of inversion *) Variable F : A -> nat -> Prop. Definition inv_lt_rel x y := exists2 n, F x n & (forall m, F y m -> n < m). Hypothesis F_compat : forall x y:A, R x y -> inv_lt_rel x y.P:nat -> nat -> PropHrec:forall n m : nat, (forall p0 q : nat, p0 < n -> P p0 q) -> (forall p0 : nat, p0 < m -> P n p0) -> P n mp:natforall n : nat, (forall m : nat, m < n -> forall m0 : nat, P m m0) -> forall m : nat, P n mA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x y : A, R x y -> inv_lt_rel x yforall x : A, (exists n : nat, F x n) -> Acc R xA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x y : A, R x y -> inv_lt_rel x yforall x : A, (exists n : nat, F x n) -> Acc R xA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x y : A, R x y -> inv_lt_rel x yn:natforall x : A, F x n -> Acc R xA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x0 y : A, R x0 y -> inv_lt_rel x0 yn, n0:natH:forall m : nat, m < n0 -> forall x0 : A, F x0 m -> Acc R x0x:Afxn:F x n0Acc R xA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x0 y0 : A, R x0 y0 -> inv_lt_rel x0 y0n, n0:natH:forall m : nat, m < n0 -> forall x0 : A, F x0 m -> Acc R x0x:Afxn:F x n0y:AH0:R y xAcc R yapply (H x0); auto. Qed.A:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x1 y0 : A, R x1 y0 -> inv_lt_rel x1 y0n, n0:natH:forall m : nat, m < n0 -> forall x1 : A, F x1 m -> Acc R x1x:Afxn:F x n0y:AH0:R y xx0:natH1:F y x0H2:forall m : nat, F x m -> x0 < mAcc R yA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x y : A, R x y -> inv_lt_rel x ywell_founded RA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x y : A, R x y -> inv_lt_rel x ywell_founded RA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x y0 : A, R x y0 -> inv_lt_rel x y0a, y:AH:R y aAcc R yA:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x0 y0 : A, R x0 y0 -> inv_lt_rel x0 y0a, y:AH:R y ax:natH0:F y xH1:forall m : nat, F a m -> x < mAcc R yexists x; trivial. Qed. End LT_WF_REL.A:SetR:A -> A -> PropF:A -> nat -> PropF_compat:forall x0 y0 : A, R x0 y0 -> inv_lt_rel x0 y0a, y:AH:R y ax:natH0:F y xH1:forall m : nat, F a m -> x < mexists n : nat, F y nforall (A : Set) (F : A -> nat -> Prop), well_founded (inv_lt_rel A F)intros; apply (well_founded_inv_lt_rel_compat A (inv_lt_rel A F) F); trivial. Qed.forall (A : Set) (F : A -> nat -> Prop), well_founded (inv_lt_rel A F)
A constructive proof that any non empty decidable subset of
natural numbers has a least element
Set Implicit Arguments. Require Import Le. Require Import Compare_dec. Require Import Decidable. Definition has_unique_least_element (A:Type) (R:A->A->Prop) (P:A->Prop) := exists! x, P x /\ forall x', P x' -> R x x'.forall P : nat -> Prop, (forall n : nat, P n \/ ~ P n) -> (exists n : nat, P n) -> has_unique_least_element le Pforall P : nat -> Prop, (forall n : nat, P n \/ ~ P n) -> (exists n : nat, P n) -> has_unique_least_element le PP:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0has_unique_least_element le PP:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0forall n : nat, (exists n' : nat, n' < n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> n <= n')P:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0H:forall n : nat, (exists n' : nat, n' < n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> n <= n')has_unique_least_element le PP:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0forall n : nat, (exists n' : nat, n' < n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> n <= n')P:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0(exists n' : nat, n' < 0 /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> 0 <= n')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIHn:(exists n' : nat, n' < n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> n <= n')(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')P:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0(exists n' : nat, n' < 0 /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> 0 <= n')P:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0forall n' : nat, P n' -> 0 <= n'apply Nat.le_0_l.P:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0n':natH:P n'0 <= n'P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIHn:(exists n' : nat, n' < n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> n <= n')(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n, n':natIH1:n' < nIH2:P n' /\ (forall n'' : nat, P n'' -> n' <= n'')(exists n'0 : nat, n'0 < S n /\ P n'0 /\ (forall n'' : nat, P n'' -> n'0 <= n'')) \/ (forall n'0 : nat, P n'0 -> S n <= n'0)P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n, n':natIH1:n' < nIH2:P n' /\ (forall n'' : nat, P n'' -> n' <= n'')(exists n'0 : nat, n'0 < S n /\ P n'0 /\ (forall n'' : nat, P n'' -> n'0 <= n'')) \/ (forall n'0 : nat, P n'0 -> S n <= n'0)exists n'; auto with arith.P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n, n':natIH1:n' < nIH2:P n' /\ (forall n'' : nat, P n'' -> n' <= n'')exists n'0 : nat, n'0 < S n /\ P n'0 /\ (forall n'' : nat, P n'' -> n'0 <= n'')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'HP:P n(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'HP:~ P n(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'HP:P n(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')exists n; auto with arith.P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'HP:P nexists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'HP:~ P n(exists n' : nat, n' < S n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> S n <= n')P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'HP:~ P nforall n' : nat, P n' -> S n <= n'P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n'0 : nat, P n'0 -> n <= n'0HP:~ P nn':natHn':P n'S n <= n'P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n'0 : nat, P n'0 -> n <= n'0HP:~ P nn':natHn':P n'n <> n'auto.P:nat -> PropPdec:forall n1 : nat, P n1 \/ ~ P n1n0:natHPn0:P n0n:natIH:forall n' : nat, P n' -> n <= n'HP:~ P nHn':P nFalsedestruct (H n0) as [(n & H1 & H2 & H3)|H0]; [exists n | exists n0]; repeat split; trivial; intros n' (HPn',Hn'); apply Nat.le_antisymm; auto. Qed. Unset Implicit Arguments. Notation iter_nat n A f x := (nat_rect (fun _ => A) x (fun _ => f) n) (only parsing).P:nat -> PropPdec:forall n : nat, P n \/ ~ P nn0:natHPn0:P n0H:forall n : nat, (exists n' : nat, n' < n /\ P n' /\ (forall n'' : nat, P n'' -> n' <= n'')) \/ (forall n' : nat, P n' -> n <= n')has_unique_least_element le P