File: classical_orders.v

package info (click to toggle)
mathcomp-analysis 1.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,308 kB
  • sloc: sh: 420; python: 76; sed: 25; makefile: 7
file content (358 lines) | stat: -rw-r--r-- 13,506 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
From mathcomp Require Import all_ssreflect ssralg ssrnum interval.
From mathcomp Require Import mathcomp_extra boolp classical_sets.
From HB Require Import structures.
From mathcomp Require Import functions set_interval.

(**md**************************************************************************)
(* # classical orders                                                         *)
(*                                                                            *)
(* This file provides some additional order theory that requires stronger     *)
(* axioms than mathcomp's own orders expect.                                  *)
(* ```                                                                        *)
(*     same_prefix n == two elements in a product space agree up n            *)
(*    first_diff x y == the first occurrence where x n != y n, or None        *)
(*       big_lexi_le == the (countably) infinite lexicographical ordering     *)
(*    big_lexi_order == an alias for attaching this order type                *)
(*  start_with n x y == x for the first n values, then switches to y          *)
(* ```                                                                        *)
(*                                                                            *)
(******************************************************************************)

Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Import Order.TTheory GRing.Theory Num.Def Num.Theory.

Local Open Scope classical_set_scope.

Definition big_lexi_order {I : Type} (T : I -> Type) : Type := forall i, T i.
HB.instance Definition _ (I : Type) (K : I -> choiceType) :=
  Choice.on (big_lexi_order K).

Section big_lexi_le.
Context {K : nat -> eqType}.

Definition same_prefix n (t1 t2 : forall n, K n) :=
  forall m, (m < n)%O -> t1 m = t2 m.

Lemma same_prefix0 t1 t2 : same_prefix 0 t1 t2. Proof. by []. Qed.
Hint Resolve same_prefix0 : core.

Lemma same_prefix_sym n t1 t2 : same_prefix n t1 t2 <-> same_prefix n t2 t1.
Proof. by rewrite /same_prefix; split => + m mn => /(_ m mn). Qed.

Lemma same_prefix_leq n m t1 t2 :
  n <= m -> same_prefix m t1 t2 -> same_prefix n t1 t2.
Proof.
move=> nm + r rn; apply.
by move: nm; rewrite leq_eqVlt => /predU1P[<-//|]; exact: ltn_trans.
Qed.

Lemma same_prefix_refl n x : same_prefix n x x. Proof. by []. Qed.

Lemma same_prefix_trans n x y z :
  same_prefix n x y ->
  same_prefix n y z ->
  same_prefix n x z.
Proof. by move=> + + m mn => /(_ _ mn) ->; exact. Qed.

Definition first_diff (t1 t2 : forall n, K n) : option nat :=
  xget None (Some @` [set n | same_prefix n t1 t2 /\ t1 n != t2 n]).

Lemma first_diff_sym t1 t2 : first_diff t1 t2 = first_diff t2 t1.
Proof.
rewrite /first_diff /=; congr (xget _ (image _ _)).
under eq_set do rewrite eq_sym.
by apply/seteqP; split => z/= [] /same_prefix_sym.
Qed.

Lemma first_diff_unique (x y : forall n, K n) n m :
  same_prefix n x y -> x n != y n ->
  same_prefix m x y -> x m != y m ->
  n = m.
Proof.
move=> nfx xyn mfx xym; apply/eqP; rewrite eq_le 2!leNgt; apply/andP; split.
by apply/negP => /nfx; exact/eqP.
by apply/negP => /mfx; exact/eqP.
Qed.

Lemma first_diff_SomeP x y n :
  first_diff x y = Some n <-> same_prefix n x y /\ x n != y n.
Proof.
split => [|[pfx xNy]]; rewrite /first_diff.
  by case: xgetP=> //= -[m ->|//] [p + <-[]] => /[swap] ->.
case: xgetP => /=; last by move=> /(_ (Some n))/forall2NP/(_ n)[/not_andP[]|].
by move=> [m|? []//] -> [p [pxy xyp]] <-; rewrite (@first_diff_unique x y n p).
Qed.

Lemma first_diff_NoneP t1 t2 : t1 = t2 <-> first_diff t1 t2 = None.
Proof.
rewrite /first_diff; split => [->|].
  by case: xgetP => //= -[n|//] -> [m []]; rewrite eqxx.
case: xgetP => [? -> [i /=] [?] ? <-//|/= R _].
apply/functional_extensionality_dep.
suff : forall n x, x < n -> t1 x = t2 x by move=> + n => /(_ n.+1)/(_ n); exact.
elim => [//|n ih x]; rewrite ltnS leq_eqVlt => /predU1P[->|xn]; last exact: ih.
by have /forall2NP/(_ n)[/not_andP[//|/negP/negPn/eqP]|] := R (Some n).
Qed.

Lemma first_diff_lt a x y n m :
  n < m ->
  first_diff a x = Some n ->
  first_diff a y = Some m ->
  first_diff x y = Some n.
Proof.
move=> nm /first_diff_SomeP [xpfx xE] /first_diff_SomeP [ypfx yE].
apply/first_diff_SomeP; split; last by rewrite -(ypfx _ nm) eq_sym.
by move=> o /[dup] on /xpfx <-; exact/ypfx/(ltn_trans on).
Qed.
Arguments first_diff_lt a {x y n m}.

Lemma first_diff_eq a x y n m :
  first_diff a x = Some n ->
  first_diff a y = Some n ->
  first_diff x y = Some m ->
  n <= m.
Proof.
case/first_diff_SomeP => axPfx axn /first_diff_SomeP[ayPfx ayn].
case/first_diff_SomeP => xyPfx; apply: contraNleq => mn.
by rewrite -(ayPfx _ mn) -(axPfx _ mn).
Qed.

Lemma first_diff_dfwith (x : forall n : nat, K n) i b :
  x i != b <-> first_diff x (dfwith x i b) = Some i.
Proof.
split => [xBn|/first_diff_SomeP[_]]; last by rewrite dfwithin.
apply/first_diff_SomeP; split; last by rewrite dfwithin.
by move=> n ni; rewrite dfwithout// gt_eqF.
Qed.

Definition big_lexi_le
    (R : forall n, K n -> K n -> bool) (t1 t2 : forall n, K n) :=
  if first_diff t1 t2 is Some n then R n (t1 n) (t2 n) else true.

Lemma big_lexi_le_reflexive R : reflexive (big_lexi_le R).
Proof.
move=> x; rewrite /big_lexi_le /= /first_diff.
by case: xgetP => //= -[n _|//] [m []]; rewrite eqxx.
Qed.

Lemma big_lexi_le_anti R : (forall n, antisymmetric (R n)) ->
  antisymmetric (big_lexi_le R).
Proof.
move=> antiR x y /andP[xy yx]; apply/first_diff_NoneP; move: xy yx.
rewrite /big_lexi_le first_diff_sym.
case E : (first_diff y x) => [n|]// Rxy Ryx.
case/first_diff_SomeP : E => _.
by apply: contra_neqP => _; apply/antiR; rewrite Ryx.
Qed.

Lemma big_lexi_le_trans R :
  (forall n, transitive (R n)) ->
  (forall n, antisymmetric (R n)) ->
  transitive (big_lexi_le R).
Proof.
move=> Rtrans Ranti y x z; rewrite /big_lexi_le /=.
case Ep : (first_diff x y) => [p|]; last by move/first_diff_NoneP : Ep ->.
case Er : (first_diff x z) => [r|]; last by move/first_diff_NoneP : Er ->.
case Eq : (first_diff y z) => [q|]; first last.
  by move: Ep Er; move/first_diff_NoneP: Eq => -> -> [->].
have [pq|qp|pqE]:= ltgtP p q.
- move: Er.
  rewrite (first_diff_lt y pq)// 1?first_diff_sym// => -[<-] ? _.
  by case/first_diff_SomeP : Eq => /(_ _ pq) <-.
- move: Er.
  rewrite first_diff_sym (first_diff_lt y qp)// 1?first_diff_sym// => -[<-] _ ?.
  by case/first_diff_SomeP: Ep => /(_ _ qp) ->.
- move: Ep Eq; rewrite pqE => Eqx Eqz.
  rewrite first_diff_sym in Eqx; have := first_diff_eq Eqx Eqz Er.
  rewrite leq_eqVlt => /predU1P[->|qr]; first exact: Rtrans.
  case/first_diff_SomeP : Er => /(_ _ qr) -> _ qzy qyz.
  case/first_diff_SomeP : Eqz => _; apply: contra_neqP => _.
  by apply/Ranti/andP; split.
Qed.

Lemma big_lexi_le_total R : (forall n, total (R n)) -> total (big_lexi_le R).
Proof.
move=> Rtotal x y.
case E : (first_diff x y) => [n|]; first last.
  by move/first_diff_NoneP : E ->; rewrite big_lexi_le_reflexive.
by rewrite /big_lexi_le E first_diff_sym E; exact: Rtotal.
Qed.

Definition start_with n (t1 t2 : forall n, K n) (i : nat) : K i :=
  if (i < n)%O then t1 i else t2 i.

Lemma start_with_prefix n x y : same_prefix n x (start_with n x y).
Proof. by move=> r rn; rewrite /start_with rn. Qed.

End big_lexi_le.

Section big_lexi_porder.
Context {d} {K : nat -> porderType d}.

Let Rn n (k1 k2 : K n) := (k1 <= k2)%O.

Local Lemma big_lexi_ord_reflexive : reflexive (big_lexi_le Rn).
Proof. exact: big_lexi_le_reflexive. Qed.

Local Lemma big_lexi_ord_anti : antisymmetric (big_lexi_le Rn).
Proof. by apply: big_lexi_le_anti => n; exact: le_anti. Qed.

Local Lemma big_lexi_ord_trans : transitive (big_lexi_le Rn).
Proof. by apply: big_lexi_le_trans => n; [exact: le_trans|exact: le_anti]. Qed.

HB.instance Definition _ := Order.Le_isPOrder.Build d (big_lexi_order K)
  big_lexi_ord_reflexive big_lexi_ord_anti big_lexi_ord_trans.

Lemma leEbig_lexi_order (a b : big_lexi_order K) :
  (a <= b)%O = if first_diff a b is Some n then (a n <= b n)%O else true.

Proof. by []. Qed.

End big_lexi_porder.

Section big_lexi_total.
Context {d} {K : nat -> orderType d}.

Local Lemma big_lexi_ord_total : total (@Order.le _ (big_lexi_order K)).
Proof. by apply: big_lexi_le_total => ?; exact: le_total. Qed.

HB.instance Definition _ := Order.POrder_isTotal.Build _
  (big_lexi_order K) big_lexi_ord_total.

End big_lexi_total.

Section big_lexi_bottom.
Context {d} {K : nat -> bPOrderType d}.

Let b : big_lexi_order K := (fun=> \bot)%O.
Local Lemma big_lex_bot (x : big_lexi_order K) : (b <= x)%O.
Proof.
by rewrite leEbig_lexi_order; case: first_diff => // ?; exact: Order.le0x.
Qed.

HB.instance Definition _ := @Order.hasBottom.Build _
  (big_lexi_order K) b big_lex_bot.

End big_lexi_bottom.

Section big_lexi_top.
Context {d} {K : nat -> tPOrderType d}.

Let t : big_lexi_order K := (fun=> \top)%O.
Local Lemma big_lex_top (x : big_lexi_order K) : (x <= t)%O.
Proof.
by rewrite leEbig_lexi_order; case: first_diff => // ?; exact: Order.lex1.
Qed.

HB.instance Definition _ := @Order.hasTop.Build _
  (big_lexi_order K) t big_lex_top.

End big_lexi_top.

Section big_lexi_intervals.
Context {d} {K : nat -> orderType d}.

Lemma big_lexi_order_prefix_lt (b a x: big_lexi_order K) n :
  (a < b)%O ->
  first_diff a b = Some n ->
  same_prefix n.+1 x b ->
  (a < x)%O.
Proof.
move=> + /[dup] abD /first_diff_SomeP[pfa abN].
case E1 : (first_diff a x) => [m|]; first last.
  by move/first_diff_NoneP : E1 <- => _/(_ n (ltnSn _))/eqP/negPn; rewrite abN.
move=> ab pfx; rewrite lt_neqAle; apply/andP; split.
  by apply/eqP => /first_diff_NoneP; rewrite E1.
move: ab; rewrite lt_neqAle => /andP[ba].
rewrite 2!leEbig_lexi_order E1 abD.
suff : n = m by have := pfx n (ltnSn _) => /[swap] -> ->.
apply: (@first_diff_unique _ a x) => //=; [| |by case/first_diff_SomeP : E1..].
- by apply/(same_prefix_trans pfa)/same_prefix_sym; exact: same_prefix_leq.
- by rewrite (pfx n (ltnSn _)).
Qed.

Lemma big_lexi_order_prefix_gt (b a x : big_lexi_order K) n :
  (b < a)%O ->
  first_diff a b = Some n ->
  same_prefix n.+1 x b ->
  (x < a)%O.
Proof.
move=> + /[dup] abD /first_diff_SomeP[pfa /eqP abN].
case E1 : (first_diff x a) => [m|]; first last.
  by move/first_diff_NoneP : E1 -> => _ /(_ n (ltnSn _)).
move=> ab pfx; rewrite lt_neqAle; apply/andP; split.
  by apply/negP => /eqP/first_diff_NoneP; rewrite E1.
move: ab; rewrite lt_neqAle => /andP[ba].
rewrite 2!leEbig_lexi_order (@first_diff_sym _ b a) E1 abD.
suff : n = m by have := pfx n (ltnSn _) => /[swap] -> ->.
apply: (@first_diff_unique _ x a) => //=; [| |by case/first_diff_SomeP : E1..].
- apply/same_prefix_sym/(same_prefix_trans pfa)/same_prefix_sym.
  exact: same_prefix_leq.
- by rewrite (pfx n (ltnSn _)) eq_sym; exact/eqP.
Qed.

Lemma big_lexi_order_between (a x b : big_lexi_order K) n :
  (a <= x <= b)%O ->
  same_prefix n a b ->
  same_prefix n x a.
Proof.
move=> axb; elim: n => // n IH pfxSn m mSn.
have pfxA : same_prefix n a x.
  exact/same_prefix_sym/IH/(same_prefix_leq _  pfxSn).
have pfxB : same_prefix n x b.
  apply: (@same_prefix_trans _ n x a b); first exact/same_prefix_sym.
  exact: (same_prefix_leq _  pfxSn).
move: mSn; rewrite ltEnat/= ltnS leq_eqVlt => /predU1P[->|]; first last.
  by move: pfxA; rewrite same_prefix_sym; exact.
apply: le_anti; apply/andP; split.
  case/andP: axb => ? +; rewrite leEbig_lexi_order (pfxSn n (ltnSn _)).
  case E : (first_diff x b) => [r|]; last by move/first_diff_NoneP : E ->.
  move=> xrb; have : n <= r.
    rewrite leqNgt; apply/negP=> /[dup] /pfxB xbE.
    by case/first_diff_SomeP : E => _; rewrite xbE eqxx.
  rewrite leq_eqVlt => /predU1P[->//|nr].
  by case/first_diff_SomeP : E => /(_ n nr) ->.
case/andP : axb => + ?; rewrite leEbig_lexi_order.
case E : (first_diff a x) => [r|]; last by move/first_diff_NoneP : E => <-.
move=> xrb.
have : n <= r.
  rewrite leqNgt; apply/negP => /[dup] /pfxA xbE.
  by case/first_diff_SomeP : E => _; rewrite xbE eqxx.
rewrite leq_eqVlt => /predU1P[->//|nr].
by case/first_diff_SomeP : E => /(_ n nr) ->.
Qed.

Lemma big_lexi_order_interval_prefix (i : interval (big_lexi_order K))
    (x : big_lexi_order K) :
  itv_open_ends i -> x \in i ->
  exists n, same_prefix n x `<=` [set` i].
Proof.
move: i; case=> [][[]l|[]] [[]r|[]] [][]; rewrite ?in_itv /= ?andbT.
- move=> /andP[lx xr].
  case E1 : (first_diff l x) => [m|]; first last.
    by move: lx; move/first_diff_NoneP : E1 ->; rewrite bnd_simp.
  case E2 : (first_diff x r) => [n|]; first last.
    by move: xr; move/first_diff_NoneP : E2 ->; rewrite bnd_simp.
  exists (Order.max n m).+1 => p xppfx; rewrite set_itvE.
  apply/andP; split.
    apply: (big_lexi_order_prefix_lt lx E1) => w wm; apply/esym/xppfx.
    by move/ltnSE/leq_ltn_trans : wm; apply; rewrite ltnS leq_max leqnn orbT.
  rewrite first_diff_sym in E2.
  apply: (big_lexi_order_prefix_gt xr E2) => w wm; apply/esym/xppfx.
  by move/ltnSE/leq_ltn_trans : wm; apply; rewrite ltnS leq_max leqnn.
- move=> lx.
  case E1 : (first_diff l x) => [m|]; first last.
    by move: lx; move/first_diff_NoneP : E1 ->; rewrite bnd_simp.
  exists m.+1 => p xppfx; rewrite set_itvE /=.
  by apply: (big_lexi_order_prefix_lt lx E1) => w wm; exact/esym/xppfx.
- move=> xr.
  case E2 : (first_diff x r) => [n|]; first last.
    by move: xr; move/first_diff_NoneP : E2 ->; rewrite bnd_simp.
  exists n.+1; rewrite first_diff_sym in E2 => p xppfx.
  rewrite set_itvE /=.
  by apply: (big_lexi_order_prefix_gt xr E2) => w wm; exact/esym/xppfx.
by move=> _; exists 0 => ? ?; rewrite set_itvE.
Qed.
End big_lexi_intervals.