Module mathcomp.classical.wochoice
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.From mathcomp Require Import boolp contra.
Set SsrOldRewriteGoalsOrder.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Definition
nonempty : forall {T : Type}, {pred T} -> Prop nonempty is not universe polymorphic Arguments nonempty {T}%_type_scope A nonempty is transparent Expands to: Constant mathcomp.classical.wochoice.nonempty Declared in library mathcomp.classical.wochoice, line 41, characters 11-19
Section LocalProperties.
Context {T1 T2 T3 : Type} {T : predArgType}.
Implicit Type A : {pred T}.
Local Notation "{ 'allA' P }" := (forall A : {pred T}, P A : Prop) (at level 0).
Local Notation ph := (phantom _).
Definition
prop_within : forall {T : predArgType}, mem_pred T -> forall [P : {pred T} -> Prop], phantom Prop (forall A : {pred T}, P A : Prop) -> Prop prop_within is not universe polymorphic Arguments prop_within {T}%_type_scope d [P]%_function_scope _ prop_within is transparent Expands to: Constant mathcomp.classical.wochoice.prop_within Declared in library mathcomp.classical.wochoice, line 50, characters 11-22
Lemma withinW A P : {allA P} -> prop_within (mem A) (inPhantom {allA P}).
Proof.
Lemma withinT P : prop_within (mem T) (inPhantom {allA P}) -> {allA P}.
Proof.
Lemma sub_within d d' P :
sub_mem d d' -> forall phP, @prop_within d' P phP -> @prop_within d P phP.
Proof.
End LocalProperties.
Notation "{ 'in' <= S , P }" :=
(prop_within (mem S) (inPhantom P)) : type_scope.
Section RelDefs.
Variables (T : Type) (R : rel T).
Implicit Types (x y z : T) (A C : {pred T}).
Definition
maximal : forall [T : Type], rel T -> T -> Prop maximal is not universe polymorphic Arguments maximal [T]%_type_scope R z maximal is transparent Expands to: Constant mathcomp.classical.wochoice.maximal Declared in library mathcomp.classical.wochoice, line 72, characters 11-18
Definition
minimal : forall [T : Type], rel T -> T -> Prop minimal is not universe polymorphic Arguments minimal [T]%_type_scope R z minimal is transparent Expands to: Constant mathcomp.classical.wochoice.minimal Declared in library mathcomp.classical.wochoice, line 74, characters 11-18
Definition
upper_bound : forall [T : Type], rel T -> {pred T} -> T -> Prop upper_bound is not universe polymorphic Arguments upper_bound [T]%_type_scope R A z upper_bound is transparent Expands to: Constant mathcomp.classical.wochoice.upper_bound Declared in library mathcomp.classical.wochoice, line 76, characters 11-22
Definition
lower_bound : forall [T : Type], rel T -> {pred T} -> T -> Prop lower_bound is not universe polymorphic Arguments lower_bound [T]%_type_scope R A z lower_bound is transparent Expands to: Constant mathcomp.classical.wochoice.lower_bound Declared in library mathcomp.classical.wochoice, line 78, characters 11-22
Definition
preorder : forall [T : Type], rel T -> Prop preorder is not universe polymorphic Arguments preorder [T]%_type_scope R preorder is transparent Expands to: Constant mathcomp.classical.wochoice.preorder Declared in library mathcomp.classical.wochoice, line 80, characters 11-19
Definition
partial_order : forall [T : Type], rel T -> Prop partial_order is not universe polymorphic Arguments partial_order [T]%_type_scope R partial_order is transparent Expands to: Constant mathcomp.classical.wochoice.partial_order Declared in library mathcomp.classical.wochoice, line 82, characters 11-24
Definition
total_order : forall [T : Type], rel T -> Prop total_order is not universe polymorphic Arguments total_order [T]%_type_scope R total_order is transparent Expands to: Constant mathcomp.classical.wochoice.total_order Declared in library mathcomp.classical.wochoice, line 84, characters 11-22
Definition
minimum_of : forall [T : Type], rel T -> {pred T} -> T -> Prop minimum_of is not universe polymorphic Arguments minimum_of [T]%_type_scope R A z minimum_of is transparent Expands to: Constant mathcomp.classical.wochoice.minimum_of Declared in library mathcomp.classical.wochoice, line 86, characters 11-21
Definition
maximum_of : forall [T : Type], rel T -> {pred T} -> T -> Prop maximum_of is not universe polymorphic Arguments maximum_of [T]%_type_scope R A z maximum_of is transparent Expands to: Constant mathcomp.classical.wochoice.maximum_of Declared in library mathcomp.classical.wochoice, line 88, characters 11-21
Definition
well_order : forall [T : Type], rel T -> Prop well_order is not universe polymorphic Arguments well_order [T]%_type_scope R well_order is transparent Expands to: Constant mathcomp.classical.wochoice.well_order Declared in library mathcomp.classical.wochoice, line 90, characters 11-21
Definition
chain : forall [T : Type], rel T -> {pred T} -> Prop chain is not universe polymorphic Arguments chain [T]%_type_scope R C chain is transparent Expands to: Constant mathcomp.classical.wochoice.chain Declared in library mathcomp.classical.wochoice, line 92, characters 11-16
Definition
wo_chain : forall [T : Type], rel T -> {pred T} -> Prop wo_chain is not universe polymorphic Arguments wo_chain [T]%_type_scope R C wo_chain is transparent Expands to: Constant mathcomp.classical.wochoice.wo_chain Declared in library mathcomp.classical.wochoice, line 94, characters 11-19
Lemma antisymmetric_wo_chain C :
{in C &, antisymmetric R} ->
{in <= C, forall A, nonempty A -> exists z, minimum_of A z} ->
wo_chain C.
Proof.
by apply: Ranti; rewrite ?sAC ?lbAx ?lbAz.
Qed.
Lemma antisymmetric_well_order :
antisymmetric R -> (forall A, nonempty A -> exists z, minimum_of A z) ->
well_order.
Proof.
End RelDefs.
Lemma wo_chainW (T : eqType) R C : @wo_chain T R C -> chain R C.
Proof.
Lemma wo_chain_reflexive (T : eqType) R C : @wo_chain T R C -> {in C, reflexive R}.
Lemma wo_chain_antisymmetric (T : eqType) R C : @wo_chain T R C -> {in C &, antisymmetric R}.
Proof.
have all_mem s: all [mem s : seq T] s by apply/allP.
move/[dup]/wo_chainW => Rtotal /[dup]/wo_chain_reflexive Rxx Rwo x y xC yC.
have /Rwo[] := ne_cons x [::y]; first exact/allP/and3P.
move=> z [_ Uz] /andP[Rxy Ryx]; have /and3P[xy_x xy_y _] := all_mem [:: x; y].
by rewrite -(Uz x) ?(Uz y); split=> //; apply/allP; rewrite /= (Rxy, Ryx) Rxx.
Qed.
Section Zorn.
Lemma Zorn's_lemma (T : eqType) (R : rel T) (S : {pred T}) :
{in S, reflexive R} -> {in S & &, transitive R} ->
{in <= S, forall C, wo_chain R C -> exists2 z, z \in S & upper_bound R C z} ->
{z : T | z \in S & {in S, maximal R z}}.
Proof.
preorder R -> (forall C, Well C -> {z | upper_bound R C z}) ->
{z | maximal R z}.
- move=> Rxx Rtr UBch; pose T1 := {x | x \in S}.
have S_T1 (u : T1): val u \in S by case: u.
have [|C1 chC1|u maxT1u] := Zorn T1 (relpre val R); last 1 first.
- by exists (val u) => // x Sx Rux; apply: (maxT1u (Sub x Sx)).
- by split=> [x|y x z]; [apply: Rxx | apply: Rtr].
pose C := [pred x | oapp (mem C1) false (insub x)].
have sC1C u: u \in C1 -> val u \in C by rewrite inE valK.
have memC x: x \in C -> {u | u \in C1 & val u = x}.
by rewrite inE; case: insubP => //= u _ <-; exists u.
apply/cid; suffices /UBch[_ /memC[u _ <-]//|z Sz ubCz]: wo_chain R C.
by exists (Sub z Sz) => u C1u; apply/ubCz/sC1C.
move=> A sAC [x0 Ax0].
have [||w [[C1w minC1w] Uw]] := chC1 [preim val of A].
- by move=> v /sAC; rewrite inE valK.
- by have /sAC/memC[u0 C1u0 Du0] := Ax0; exists u0; rewrite inE Du0.
exists (val w); do ?[split] => // [y Ay | y [Ay minAy]].
by case/sAC/memC: Ay (Ay) => v C1v <-; apply: minC1w.
have /sAC/memC[v C1v Dv] := Ay; rewrite (Uw v) //.
by split=> [|u Au]; rewrite ?inE /= Dv // minAy.
case=> Rxx Rtr UBch; absurd_not=> nomaxR.
pose R' := [rel x y | R x y && ~~ R y x].
have{nomaxR} /all_sig[f fP] C: {z | Well C -> upper_bound R' C z}.
have /UBch[z0 _]: Well pred0 by move=> A sA0 [x /sA0].
have [/UBch[y RCy]|] := asboolP (Well C); last by exists z0.
have [z Ryz notRzy] := nomaxR y; exists z => _ x /RCy-Rxy /=.
by rewrite (Rtr y) //=; contra: notRzy => /Rtr->.
have notCf C: Well C -> f C \notin C.
by move/fP=> R'Cf; apply/negP=> /R'Cf/=; rewrite Rxx ?andbF.
pose f_ind X := Well X /\ {in X, forall x, f [pred y in X | ~~ R x y] = x}.
pose init_seg (X Y : {pred T}) :=
{subset X <= Y} /\ {in Y, forall y, y \notin X -> upper_bound R X y}.
have init_total Y Z: f_ind Y -> f_ind Z -> {init_seg Y Z} + {init_seg Z Y}.
move=> indY indZ; pose iniYZ X := `[< init_seg X Y /\ init_seg X Z >].
pose I x := `[< exists2 X, X \in iniYZ & x \in X >]; pose I1 := [predU1 f I & I].
have [iIY iIZ]: init_seg I Y /\ init_seg I Z.
split; split=> [x /asboolP[X /asboolP[[sXY _] [sXZ _]]]|]; try by move: (x).
move=> y Yy /asboolP-I'y x /asboolP[X iXYZ Xx]; have /asboolP[[_ RXY] _] := iXYZ.
by rewrite RXY //; contra: I'y; exists X.
move=> z Zz /asboolP-I'z x /asboolP[X iXYZ Xx]; have /asboolP[_ [_ RXZ]] := iXYZ.
by rewrite RXZ //; contra: I'z; exists X.
have maxI: {in iniYZ, forall X, {subset X <= I}}; last clearbody I.
by move=> X sXYZ x Xx; apply/asboolP; exists X.
have Ich: Well I by have [Ych _] := indY; apply: sub_within Ych; case: iIY.
generally have iI1, iI1Y: Y indY iIY {iniYZ maxI} / {I = Y} + {init_seg I1 Y}.
have [[Ych fY] [sIY RIY]] := (indY, iIY).
have /wo_chain_antisymmetric RYanti := Ych.
have [sYI | /notP-ltIY] := asboolP {subset Y <= I}; [left | right].
by apply/funext=> y; apply/idP/idP=> [/sIY | /sYI].
have{ltIY} /Ych[_ /andP[]//| z [[/andP/=[I'z Yz]]]]: nonempty [predD Y & I].
by have [y] := ltIY; exists y; apply/andP.
move=> minYz _; suffices Dz: f I = z.
rewrite /I1 Dz; do 2?[split] => // [x /predU1P[->|/sIY] // | y Yy].
by case/norP=> /= z'y I'y x /predU1P[->|/RIY->//]; apply/minYz/andP.
rewrite -(fY z Yz); congr f; apply/esym/funext=> x /=.
apply/idP/idP=> [/andP[Yx] | Ix]; first by contra=> I'x; apply/minYz/andP.
have Yx := sIY x Ix; rewrite Yx /=; contra: (I'z) => Rzx.
by rewrite (RYanti z x) // Rzx RIY.
case: iI1Y {iI1}(iI1 Z) => [<- _| iI1Y [||<-|iI1Z]//]; [by left | by right |].
by case/notCf/negP: Ich; apply/(maxI I1); [apply/asboolP|apply/predU1l].
pose U x := `[< exists2 X, x \in X & f_ind X >].
have Umax X: f_ind X -> init_seg X U.
move=> indX; split=> [x Xx | y]; first by apply/asboolP; exists X.
case/asboolP=> Y Yy indY notXy x Xx.
by have [[sYX _]|[_ ->//]] := init_total Y X indY indX; rewrite sYX in notXy.
have RUanti: {in U &, antisymmetric R}.
move=> x y /asboolP[X Xx indX] /asboolP[Y Yy indY].
without loss [sXY _]: x y X Y Xx Yy {indX} indY / init_seg X Y.
move=> IH.
by case: (init_total X Y) => // {}/IH-IH; [|rewrite andbC] => /IH->.
have [/wo_chain_antisymmetric RYanti _] := indY.
by apply: RYanti => //; apply: sXY.
have Uch: Well U.
apply: antisymmetric_wo_chain => // A sAU [x0 Ax0].
have /sAU/asboolP[X Xx0 indX] := Ax0.
pose B := [predI A & X]; have sBX: {subset B <= X} by move=> y /andP[].
have [[Xch _] /Umax[sXU iXU]] := (indX, indX).
have{x0 Ax0 Xx0} /Xch[//|z [[/andP[/= Az Xz] minBz] _]]: nonempty B.
by exists x0; apply/andP.
exists z; split=> // y Ay; have Uy := sAU y Ay.
by have [Xy | /iXU->//] := boolP (y \in X); apply/minBz/andP.
pose U1 := [predU1 f U & U]; have notUfU: f U \notin U by apply: notCf.
suffices indU1: f_ind U1.
by have [sU1U _] := Umax U1 indU1; rewrite sU1U ?inE ?eqxx in notUfU.
have RU1fU: upper_bound R U1 (f U) by move=> x /predU1P[-> // | /fP/andP[]] .
split=> [A sAU1 neA | x U1x].
have [sAfU | {neA}/notP[x Ax fU'x]] := asboolP {subset A <= pred1 (f U)}.
have AfU: f U \in A by have [x Ax] := neA; have /sAfU/eqP<- := Ax.
by exists (f U); split=> [|y [/sAfU/eqP//]]; split=> // _ /sAfU/eqP->.
have Ux: x \in U by case/sAU1/orP: Ax => // /idPn.
pose B := [predI A & U]; have sBU: {subset B <= U} by move=> y /andP[].
have /Uch[//|z [[/andP[/= Az Uz] minBz] _]]: nonempty B.
by exists x; apply/andP.
have{minBz} minAz: lower_bound R A z.
move=> y Ay; case/sAU1/predU1P: (Ay) => [->|/= Uy]; first exact/RU1fU/sAU1.
exact/minBz/andP.
exists z; do ?[split] => // y [Ay minAy].
have /sAU1/predU1P[Dy|Uy] := Ay; last by apply: RUanti; rewrite ?minAz ?minAy.
by have /andP[_] := fP U Uch z Uz; rewrite -Dy minAy.
have /predU1P[-> | /asboolP[X Xx indX]] := U1x.
congr f; apply/funext=> y; apply/idP/idP=> [|Uy]; last first.
by rewrite !inE unfold_in -/(U y) Uy orbT; case/andP: (fP U Uch y Uy).
by case/andP=> /predU1P[->|//]; rewrite Rxx.
have{indX} [[_ f_indX] /Umax[sXU iXU]] := (indX, indX).
rewrite -[RHS]f_indX //; congr f; apply/funext=> y; apply/andb_id2r=> notRyx.
apply/idP/idP=> [U1y | Xy]; last exact/predU1r/sXU.
by contra: notRyx => notXy; have /predU1P[->|/iXU->] := U1y; first apply/RU1fU.
Qed.
Theorem Hausdorff_maximal_principle T R (S C : {pred T}) :
{in S, reflexive R} -> {in S & &, transitive R} -> chain R C -> {subset C <= S} ->
{M : {pred T} |
[/\ {subset C <= M}, {subset M <= S}
& forall X, chain R X -> {subset M <= X} -> {subset X <= S} -> M = X]}.
Proof.
pose CSch X := `[< [/\ chain R X, {subset C <= X} & {subset X <= S}] >].
pose Rch (X Y : {pred T}) := `[< {subset X <= Y} >].
have: {in CSch & &, transitive Rch}.
by move=> X Y Z ? ? ? /asboolP-sXY /asboolP-sYZ; apply/asboolP => x /sXY/sYZ.
have /Zorn's_lemma/[apply]: {in CSch, reflexive Rch} by move=> X _; apply/asboolP.
case=> [XX CSchXX XXwo | M /asboolP[Mch sCM sMS] maxM]; last first.
exists M; split=> // X Xch sMX sXS.
suffices /asboolP-sXM: Rch X M by apply/funext=> x; apply/idP/idP=> [/sMX|/sXM].
by apply: maxM; apply/asboolP=> //; split=> // x /sCM/sMX.
move/(@wo_chainW {pred T}): XXwo => XXch.
without loss XX_C: XX CSchXX XXch / C \in XX.
have CSchC: C \in CSch by apply/asboolP; split.
have RchC_CSch X: X \in CSch -> Rch C X by case/asboolP=> _ sCX _; apply/asboolP.
pose XX1 X := `[< X = C \/ X \in XX >].
have CSchXX1: {subset XX1 <= CSch} by move=> X /asboolP[-> | /CSchXX].
case/(_ XX1)=> // [||Z CSchZ ubZ]; first 2 [by apply/asboolP; left].
move=> X Y /asboolP[-> /CSchXX1/RchC_CSch-> //| XX_X].
by rewrite orbC => /asboolP[-> | /XXch->//]; rewrite RchC_CSch ?CSchXX.
by exists Z => // X XX_X; apply/ubZ/asboolP; right.
pose D x := `[< exists2 X, X \in XX & x \in X >].
have sCD: {subset C <= D} by move=> x Cx; apply/asboolP; exists C.
have sDS: {subset D <= S} by move=> x /asboolP[X /CSchXX/asboolP[_ _ sXS] /sXS].
have in2D: {in D &, forall x y, exists X, [/\ X \in XX, x \in X & y \in X]}.
move=> x y /asboolP[X XX_X Xx] /asboolP[Y XX_Y Yy]; have:= XXch X Y XX_X XX_Y.
by case/orP=> [/asboolP/(_ x Xx)|/asboolP/(_ y Yy)]; [exists Y | exists X].
exists D => [|X XX_X]; last by apply/asboolP=> x Xx; apply/asboolP; exists X.
apply/asboolP; split=> //.
move=> x y xD /(in2D x)-/(_ xD) [X [/CSchXX/asboolP[Xch _ _] Xx Xy]].
exact: Xch.
Qed.
Theorem well_ordering_principle (T : eqType) : {R : rel T | well_order R}.
Proof.
pose srel := pred T * rel T : Type.
pose loc (R : srel) := [rel x y | [&& x \in R.1, y \in R.1 & R.2 x y]].
pose pwo (R : srel) := `[< wo_chain R.2 R.1 >].
pose init_seg (R S : srel) :=
{in R.1 & S.1, forall x y, S.2 x y = (y \in R.1) ==> R.2 x y}.
pose initR R S := `[< {subset R.1 <= S.1} /\ init_seg R S >].
have initRR: reflexive initR by move=> R; apply/asboolP; split=> // x y _ ->.
have initRtr: transitive initR.
move=> R2 R1 R3 /asboolP[D12 R12] /asboolP[D23 R23]; apply/asboolP.
split=> [x /D12/D23// | x y D1x D3y]; rewrite R23 ?(D12 x) //.
by case D2y: (y \in R2.1); [apply: R12 | rewrite (contraFF (D12 y))].
have: {in pwo & &, transitive initR} by move=> X Y Z ? ? ?; exact: initRtr.
have/Zorn's_lemma/[apply]: {in pwo, reflexive initR} by [].
case=> [C pwoC Cch | [D R] /asboolP/=pwoR maxR].
have /(@wo_chainW ({pred T} * rel T)%type) {}Cch := Cch.
pose D x := `[< exists2 S, S \in C & x \in S.1 >]; pose R x y := `[< exists2 S, S \in C & loc S x y >].
exists (D, R).
apply/asboolP=> /= X sXD [x Xx]; have /sXD/asboolP[R0 CR0 /= D0x] := Xx.
have /pwoC/asboolP/=R0wo := CR0.
have{x Xx D0x}: nonempty [predI X & R0.1] by exists x; apply/andP.
case/R0wo=> [_ /andP[]// |z [[/andP/=[Xz D0z] min0z] _]].
have{R0 CR0 R0wo D0z min0z} minXz: lower_bound R X z.
move=> y Xy; have /sXD/asboolP[R1 /= CR1 D1y] := Xy.
have /orP[/asboolP/=[D10 R10] | /asboolP/=[D01 R01]] := Cch _ _ CR1 CR0.
by apply/asboolP; exists R0; rewrite //= D0z min0z ?inE ?Xy D10.
apply/asboolP; exists R1; rewrite //= R01 ?D1y// D01//=.
by apply/implyP=> D0y; apply/min0z/andP.
exists z; split=> // y [{}/minXz/asboolP[R0 CR0 R0zy] minXy].
case/minXy/asboolP: Xz => {minXy} R1 CR1 R1yz.
without loss /asboolP[D01 R01]: y z R0 R1 CR0 CR1 R0zy R1yz / initR R0 R1.
by move=> IH; have /orP[/(IH y z)-> | /(IH z y)-> ] := Cch _ _ CR0 CR1.
have{R1yz R0zy} [/and3P[D1y D1z R1zy] /and3P[D0z D0y R0yz]] := (R1yz, R0zy).
have /pwoC/asboolP/wo_chain_antisymmetric R1anti := CR1.
by apply: R1anti => //; rewrite R1zy R01 // D0y R0yz.
move=> R0 CR0; apply/asboolP; split=> [x D0x|]; first by apply/asboolP; exists R0.
move=> x y D0x Dy; apply/asboolP/idP=> [[R1 CR1 /and3P[D1x D1y R1xy]] | R0xy].
have /orP[/asboolP[_ R10] | /asboolP[_ <- //]] := Cch _ _ CR1 CR0.
by apply/implyP=> D0y; rewrite R10 // D1y R1xy.
case/asboolP: Dy => R1 CR1 D1y.
have /orP[/asboolP[D10 _] | /asboolP[D01 R01]] := Cch _ _ CR1 CR0.
by exists R0; rewrite //= D0x (implyP R0xy) D10.
by exists R1; rewrite //= D1y D01 ?R01.
exists R; apply: withinT; apply: sub_within (pwoR) => z _; assume_not=> notDz.
pose Rz x := predU1 z (if x \in D then R x else pred0).
have /maxR/(_ _)/asboolP: ([predU1 z & D] : pred T, Rz : rel T) \in pwo.
apply/asboolP=> X sXxD neX; pose XD := [predI X & D].
have [{neX}/pwoR[_ /andP[]//|x] | sXz] := asboolP (nonempty XD); last first.
have {}sXz x: x \in X -> x = z.
move=> Xx; case/sXxD/predU1P: (Xx) => // Dx.
by case: sXz; exists x; apply/andP.
have [x Xx] := neX; exists x; have /sXz-eq_xz := Xx.
by split=> [|_ [/sXz-> //]]; split=> // _ /sXz->; apply/predU1l.
case=> -[/andP/=[Xx Dx] minXDx] Ux; exists x; split=> [|y [Xy minXy]].
split=> // y Xy; have /sXxD/predU1P[-> | Dy] := Xy; first exact/predU1l.
by rewrite /= Dx; apply/predU1r/minXDx/andP.
have Dy: y \in D.
have /minXy/= := Xx; case: ifP => // _ /idPn[].
by rewrite negb_or andbT (memPn notDz).
apply: Ux; split=> [|t /andP[/minXy]]; first exact/andP.
by rewrite /= Dy => /predU1P[-> /idPn[]|].
case=> [|/= -> //]; last exact/predU1l.
apply/asboolP; split=> [x|x y /= Dx]; first exact: predU1r.
rewrite Dx => /predU1P[-> | /= Dy]; first by rewrite eqxx (negPf notDz).
by rewrite Dy -implyNb (memPn notDz).
Qed.
End Zorn.