Skip to content

Commit b60d701

Browse files
committed
Permutations as a group + uniform distr
1 parent c996dd8 commit b60d701

File tree

1 file changed

+269
-0
lines changed

1 file changed

+269
-0
lines changed

theories/algebra/PermsGroup.eca

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
(* -------------------------------------------------------------------- *)
2+
require import AllCore List Ring Binomial Perms FinType Finite Distr.
3+
require (*--*) Subtype.
4+
5+
(* -------------------------------------------------------------------- *)
6+
type t.
7+
8+
clone FinType as FinT with type t <- t.
9+
10+
hint simplify FinT.enumP.
11+
12+
hint exact : FinT.enum_uniq.
13+
14+
(* -------------------------------------------------------------------- *)
15+
(* FIXME: move this *)
16+
lemma uniq_nth ['a] (x0 : 'a) (s : 'a list) :
17+
uniq s => forall i j, 0 <= i < size s => 0 <= j < size s =>
18+
nth x0 s i = nth x0 s j => i = j.
19+
proof.
20+
move=> uqs i j rgi rgj /(congr1 (fun x => index x s)) /=.
21+
by rewrite !index_uniq.
22+
qed.
23+
24+
(* -------------------------------------------------------------------- *)
25+
(* FIXME: move this *)
26+
lemma inj_bij (f : t -> t) : injective f => bijective f.
27+
proof.
28+
pose P y x := y = f x; pose g := fun y => choiceb (P y) witness.
29+
move=> inj_f; exists g; split.
30+
- move=> x @/g; have := choicebP (P (f x)) witness _ => /=.
31+
- by exists x. - by move/inj_f => /eq_sym.
32+
move=> y @/g; have /eq_sym // := choicebP (P y) witness _ => /=.
33+
pose s := map f FinT.enum; suff: perm_eq s FinT.enum.
34+
- by move/perm_eq_mem/(_ y) => /= /mapP[x] /= ->; exists x.
35+
have uqs: uniq s by rewrite map_inj_in_uniq //#.
36+
apply/perm_eq_sym/uniq_eq_perm_eq => //; last first.
37+
- by rewrite size_map.
38+
apply/fun_ext=> x /=; rewrite eq_sym &(eqT).
39+
suff: perm_eq s FinT.enum by move/perm_eq_mem/(_ x).
40+
apply: uniq_le_perm_eq => //.
41+
- by move=> x' /=. (* ??? *)
42+
- by rewrite size_map.
43+
qed.
44+
45+
(* -------------------------------------------------------------------- *)
46+
type preperm = t -> t.
47+
48+
op isperm (p : preperm) =
49+
bijective p.
50+
51+
subtype perm as PSub = { p : preperm | isperm p }.
52+
53+
realize inhabited by exists idfun; smt().
54+
55+
(* -------------------------------------------------------------------- *)
56+
abbrev "_.[_]" (p : perm) (x : t) = (PSub.val p) x.
57+
58+
(* -------------------------------------------------------------------- *)
59+
op preperm1 : preperm =
60+
idfun.
61+
62+
op prepermM (p1 p2 : preperm) =
63+
p1 \o p2.
64+
65+
op prepermV (p : preperm) =
66+
choiceb (fun pV => cancel p pV) witness.
67+
68+
(* -------------------------------------------------------------------- *)
69+
lemma perm1_spec : isperm preperm1 by smt().
70+
71+
lemma permM_spec (p1 p2 : preperm) :
72+
isperm p1 => isperm p2 => isperm (prepermM p1 p2).
73+
proof. by apply: bij_comp. qed.
74+
75+
lemma permV_spec (p : preperm) :
76+
isperm p => isperm (prepermV p).
77+
proof.
78+
move=> ^bijp [pV] [can_p can_pV].
79+
have ?: cancel p (prepermV p).
80+
- apply: (choicebP (fun pV => cancel p pV) witness) => /=.
81+
by exists pV.
82+
suff ->: prepermV p = pV by smt(bij_can_bij).
83+
- by apply/fun_ext; apply: (bij_can_eq _ _ _ bijp) => //#.
84+
qed.
85+
86+
(* -------------------------------------------------------------------- *)
87+
op perm1 =
88+
PSub.insubd preperm1.
89+
90+
op ( \o ) (p1 p2 : perm) =
91+
PSub.insubd (prepermM (PSub.val p1) (PSub.val p2)).
92+
93+
op [ ! ] (p : perm) =
94+
PSub.insubd (prepermV (PSub.val p)).
95+
96+
(* -------------------------------------------------------------------- *)
97+
lemma perm1E (x : t) : perm1.[x] = x.
98+
proof. by rewrite /perm1 PSub.val_insubd ifT // &(perm1_spec). qed.
99+
100+
lemma permME (p1 p2 : perm) (x : t) : (p1 \o p2).[x] = p1.[p2.[x]].
101+
proof. by rewrite /(+) PSub.val_insubd ifT 1:(permM_spec) // PSub.valP. qed.
102+
103+
hint simplify perm1E, permME.
104+
105+
(* -------------------------------------------------------------------- *)
106+
lemma perm_eqP (p1 p2 : perm) :
107+
(p1 = p2) <=> (forall x, p1.[x] = p2.[x]).
108+
proof. by split=> [->//|eqext]; apply/PSub.val_inj/fun_ext. qed.
109+
110+
(* -------------------------------------------------------------------- *)
111+
lemma mulpA: associative (\o).
112+
proof. by move=> p q r; apply/perm_eqP=> x. qed.
113+
114+
(* -------------------------------------------------------------------- *)
115+
lemma mulp1: left_id perm1 (\o).
116+
proof. by move=> p; apply/perm_eqP=> x. qed.
117+
118+
(* -------------------------------------------------------------------- *)
119+
lemma mul1p: right_id perm1 (\o).
120+
proof. by move=> p; apply/perm_eqP=> x. qed.
121+
122+
(* -------------------------------------------------------------------- *)
123+
lemma mulpV : right_inverse perm1 [!] (\o).
124+
proof.
125+
move=> p; apply/perm_eqP=> x /=.
126+
rewrite /[!] PSub.insubdK 1:&(permV_spec) 1:(PSub.valP).
127+
have ->//: cancel (prepermV (PSub.val p)) (PSub.val p).
128+
apply/bij_can_sym; first by apply/PSub.valP.
129+
apply: (choicebP(fun pV => cancel (PSub.val p) pV) witness).
130+
by case: (PSub.valP p) => g [] *; exists g.
131+
qed.
132+
133+
(* -------------------------------------------------------------------- *)
134+
lemma mulpVE (p : perm) (x : t) : p.[(!p).[x]] = x.
135+
proof. by rewrite -permME mulpV. qed.
136+
137+
hint simplify mulpVE.
138+
139+
(* -------------------------------------------------------------------- *)
140+
lemma bij_perm (p : perm) : bijective (PSub.val p).
141+
proof. by apply: PSub.valP. qed.
142+
143+
(* -------------------------------------------------------------------- *)
144+
lemma inj_perm (p : perm) : injective (PSub.val p).
145+
proof. by apply: (bij_inj _ (bij_perm p)). qed.
146+
147+
(* -------------------------------------------------------------------- *)
148+
hint simplify mulp1, mul1p, mulpV.
149+
150+
(* -------------------------------------------------------------------- *)
151+
op tolist (p : perm) : t list =
152+
map (fun x => p.[x]) FinT.enum.
153+
154+
(* -------------------------------------------------------------------- *)
155+
op pre_oflist (s : t list) : preperm =
156+
fun x => nth witness s (index x FinT.enum).
157+
158+
(* -------------------------------------------------------------------- *)
159+
op oflist (s : t list) : perm =
160+
PSub.insubd (pre_oflist s).
161+
162+
(* -------------------------------------------------------------------- *)
163+
lemma isperm_pre_oflist (s : t list) :
164+
perm_eq s FinT.enum => isperm (pre_oflist s).
165+
proof.
166+
move=> sfull; apply: inj_bij => x y @/pre_oflist.
167+
have eqsz: size s = size FinT.enum by apply: perm_eq_size.
168+
have hid_x: 0 <= index x FinT.enum < size s.
169+
- by rewrite index_ge0 /= eqsz index_mem.
170+
have hid_y: 0 <= index y FinT.enum < size s.
171+
- by rewrite index_ge0 /= eqsz index_mem.
172+
have: uniq s by rewrite (perm_eq_uniq _ _ sfull).
173+
move/uniq_nth => + eqnth - /(_ witness _ _ hid_x hid_y eqnth).
174+
by move/(congr1 (nth witness FinT.enum)); rewrite !nth_index.
175+
qed.
176+
177+
(* -------------------------------------------------------------------- *)
178+
lemma oflistE (s : t list) (x : t) :
179+
perm_eq s FinT.enum => (oflist s).[x] = nth witness s (index x FinT.enum).
180+
proof. by move/isperm_pre_oflist => h; rewrite PSub.insubdK. qed.
181+
182+
(* -------------------------------------------------------------------- *)
183+
lemma tolist_nth_index (p : perm) (x : t) :
184+
nth witness (tolist p) (index x FinT.enum) = p.[x].
185+
proof.
186+
rewrite /tolist (nth_map witness) -1:nth_index //.
187+
by rewrite index_ge0 index_mem.
188+
qed.
189+
190+
(* -------------------------------------------------------------------- *)
191+
lemma perm_tolist (p : perm) : perm_eq (tolist p) FinT.enum.
192+
proof.
193+
apply/perm_eq_sym/uniq_eq_perm_eq.
194+
- by apply: FinT.enum_uniq.
195+
- apply/fun_ext=> x; rewrite eq_sym /= eqT.
196+
by apply/mapP; exists (!p).[x].
197+
- by rewrite size_map.
198+
qed.
199+
200+
(* -------------------------------------------------------------------- *)
201+
lemma inj_tolist : injective tolist.
202+
proof.
203+
move=> p q; apply/contraLR; rewrite perm_eqP negb_forall.
204+
case=> x neq; pose i := index x FinT.enum.
205+
apply/negP => /(congr1 (fun s => nth witness s i)) /=.
206+
by rewrite !tolist_nth_index.
207+
qed.
208+
209+
(* -------------------------------------------------------------------- *)
210+
lemma inj_oflist (p q : t list) :
211+
perm_eq p FinT.enum
212+
=> perm_eq q FinT.enum
213+
=> oflist p = oflist q
214+
=> p = q.
215+
proof.
216+
move=> hp hq eq; apply: (eq_from_nth witness).
217+
- by rewrite (perm_eq_size _ _ hp) (perm_eq_size _ _ hq).
218+
move=> i; rewrite (perm_eq_size _ _ hp) => rgi.
219+
pose x := nth witness FinT.enum i.
220+
move/(congr1 PSub.val): eq => /fun_ext /(_ x).
221+
by rewrite !oflistE // !index_uniq.
222+
qed.
223+
224+
(* -------------------------------------------------------------------- *)
225+
lemma oflistK : cancel tolist oflist.
226+
proof.
227+
move=> p; apply/perm_eqP=> x; rewrite oflistE 1:&(perm_tolist).
228+
rewrite (nth_map witness) /=.
229+
- by rewrite index_ge0 /= index_mem.
230+
- by rewrite nth_index.
231+
qed.
232+
233+
(* -------------------------------------------------------------------- *)
234+
op dperm : perm distr = dmap (duniform (allperms FinT.enum)) oflist.
235+
236+
(* -------------------------------------------------------------------- *)
237+
lemma dperm_ll : is_lossless dperm.
238+
proof.
239+
apply/dmap_ll/duniform_ll.
240+
suff: FinT.enum \in allperms FinT.enum by smt().
241+
by rewrite allpermsP &(perm_eq_refl).
242+
qed.
243+
244+
(* -------------------------------------------------------------------- *)
245+
lemma dperm_uni : is_uniform dperm.
246+
proof.
247+
rewrite /dperm dmap_duniform.
248+
- move=> p q /allpermsP /perm_eq_sym hp /allpermsP /perm_eq_sym hq.
249+
by apply: inj_oflist.
250+
- by apply: duniform_uni.
251+
qed.
252+
253+
hint exact : dperm_uni.
254+
255+
(* -------------------------------------------------------------------- *)
256+
lemma dperm_full : is_full dperm.
257+
proof.
258+
move=> p; apply/supp_dmap; exists (tolist p); split.
259+
- by apply/supp_duniform/allpermsP/perm_eq_sym/perm_tolist.
260+
- by rewrite oflistK.
261+
qed.
262+
263+
hint exact : dperm_full.
264+
265+
(* -------------------------------------------------------------------- *)
266+
lemma dperm_funiform : is_funiform dperm.
267+
proof. by apply: is_full_funiform. qed.
268+
269+
hint exact : dperm_funiform.

0 commit comments

Comments
 (0)