cmra_big_op.v 27.1 KB
Newer Older
1
From iris.algebra Require Export cmra list.
Robbert Krebbers's avatar
Robbert Krebbers committed
2
From iris.prelude Require Import functions gmap gmultiset.
3
Set Default Proof Using "Type".
4

5
6
7
8
9
10
11
12
13
(** The operator [ [⋅] Ps ] folds [⋅] over the list [Ps]. This operator is not a
quantifier, so it binds strongly.

Apart from that, we define the following big operators with binders build in:

- The operator [ [⋅ list] k ↦ x ∈ l, P ] folds over a list [l]. The binder [x]
  refers to each element at index [k].
- The operator [ [⋅ map] k ↦ x ∈ m, P ] folds over a map [m]. The binder [x]
  refers to each element at index [k].
Dan Frumin's avatar
Dan Frumin committed
14
- The operator [ [⋅ set] x ∈ X, P ] folds over a set [X]. The binder [x] refers
15
16
17
18
19
20
21
22
  to each element.

Since these big operators are like quantifiers, they have the same precedence as
[∀] and [∃]. *)

(** * Big ops over lists *)
(* This is the basic building block for other big ops *)
Fixpoint big_op {M : ucmraT} (xs : list M) : M :=
23
  match xs with [] =>  | x :: xs => x  big_op xs end.
24
25
Arguments big_op _ !_ /.
Instance: Params (@big_op) 1.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Notation "'[⋅]' xs" := (big_op xs) (at level 20) : C_scope.

(** * Other big ops *)
Definition big_opL {M : ucmraT} {A} (l : list A) (f : nat  A  M) : M :=
  [] (imap f l).
Instance: Params (@big_opL) 2.
Typeclasses Opaque big_opL.
Notation "'[⋅' 'list' ] k ↦ x ∈ l , P" := (big_opL l (λ k x, P))
  (at level 200, l at level 10, k, x at level 1, right associativity,
   format "[⋅  list ]  k ↦ x  ∈  l ,  P") : C_scope.
Notation "'[⋅' 'list' ] x ∈ l , P" := (big_opL l (λ _ x, P))
  (at level 200, l at level 10, x at level 1, right associativity,
   format "[⋅  list ]  x  ∈  l ,  P") : C_scope.

Definition big_opM {M : ucmraT} `{Countable K} {A}
    (m : gmap K A) (f : K  A  M) : M :=
  [] (curry f <$> map_to_list m).
Instance: Params (@big_opM) 6.
Typeclasses Opaque big_opM.
Notation "'[⋅' 'map' ] k ↦ x ∈ m , P" := (big_opM m (λ k x, P))
  (at level 200, m at level 10, k, x at level 1, right associativity,
   format "[⋅  map ]  k ↦ x  ∈  m ,  P") : C_scope.
48
49
50
Notation "'[⋅' 'map' ] x ∈ m , P" := (big_opM m (λ _ x, P))
  (at level 200, m at level 10, x at level 1, right associativity,
   format "[⋅  map ]  x  ∈  m ,  P") : C_scope.
51
52
53
54
55
56
57
58

Definition big_opS {M : ucmraT} `{Countable A}
  (X : gset A) (f : A  M) : M := [] (f <$> elements X).
Instance: Params (@big_opS) 5.
Typeclasses Opaque big_opS.
Notation "'[⋅' 'set' ] x ∈ X , P" := (big_opS X (λ x, P))
  (at level 200, X at level 10, x at level 1, right associativity,
   format "[⋅  set ]  x  ∈  X ,  P") : C_scope.
59

Robbert Krebbers's avatar
Robbert Krebbers committed
60
61
62
63
64
65
66
67
Definition big_opMS {M : ucmraT} `{Countable A}
  (X : gmultiset A) (f : A  M) : M := [] (f <$> elements X).
Instance: Params (@big_opMS) 5.
Typeclasses Opaque big_opMS.
Notation "'[⋅' 'mset' ] x ∈ X , P" := (big_opMS X (λ x, P))
  (at level 200, X at level 10, x at level 1, right associativity,
   format "[⋅  'mset' ]  x  ∈  X ,  P") : C_scope.

68
69
(** * Properties about big ops *)
Section big_op.
70
71
Context {M : ucmraT}.
Implicit Types xs : list M.
72
73

(** * Big ops *)
74
75
76
77
78
Lemma big_op_Forall2 R :
  Reflexive R  Proper (R ==> R ==> R) (@op M _) 
  Proper (Forall2 R ==> R) (@big_op M).
Proof. rewrite /Proper /respectful. induction 3; eauto. Qed.

79
80
Global Instance big_op_ne : NonExpansive (@big_op M).
Proof. intros ?. apply big_op_Forall2; apply _. Qed.
81
82
83
Global Instance big_op_proper : Proper (() ==> ()) (@big_op M) := ne_proper _.

Lemma big_op_nil : [] (@nil M) = .
84
Proof. done. Qed.
85
Lemma big_op_cons x xs : [] (x :: xs) = x  [] xs.
86
Proof. done. Qed.
87
88
89
90
91
92
93
94
95
96
Lemma big_op_app xs ys : [] (xs ++ ys)  [] xs  [] ys.
Proof.
  induction xs as [|x xs IH]; simpl; first by rewrite ?left_id.
  by rewrite IH assoc.
Qed.

Lemma big_op_mono xs ys : Forall2 () xs ys  [] xs  [] ys.
Proof. induction 1 as [|x y xs ys Hxy ? IH]; simpl; eauto using cmra_mono. Qed.

Global Instance big_op_permutation : Proper (() ==> ()) (@big_op M).
97
98
Proof.
  induction 1 as [|x xs1 xs2 ? IH|x y xs|xs1 xs2 xs3]; simpl; auto.
99
100
  - by rewrite IH.
  - by rewrite !assoc (comm _ x).
101
  - by trans (big_op xs2).
102
Qed.
103

Robbert Krebbers's avatar
Robbert Krebbers committed
104
Lemma big_op_submseteq xs ys : xs + ys  [] xs  [] ys.
105
Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
106
  intros [xs' ->]%submseteq_Permutation.
107
  rewrite big_op_app; apply cmra_included_l.
108
Qed.
109
110

Lemma big_op_delete xs i x : xs !! i = Some x  x  [] delete i xs  [] xs.
111
112
Proof. by intros; rewrite {2}(delete_Permutation xs i x). Qed.

113
Lemma big_sep_elem_of xs x : x  xs  x  [] xs.
114
Proof.
115
116
  intros [i ?]%elem_of_list_lookup. rewrite -big_op_delete //.
  apply cmra_included_l.
117
Qed.
118
119
120
121
122
123
124

(** ** Big ops over lists *)
Section list.
  Context {A : Type}.
  Implicit Types l : list A.
  Implicit Types f g : nat  A  M.

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  Lemma big_opL_nil f : ([ list] ky  nil, f k y) = .
  Proof. done. Qed.
  Lemma big_opL_cons f x l :
    ([ list] ky  x :: l, f k y) = f 0 x  [ list] ky  l, f (S k) y.
  Proof. by rewrite /big_opL imap_cons. Qed.
  Lemma big_opL_singleton f x : ([ list] ky  [x], f k y)  f 0 x.
  Proof. by rewrite big_opL_cons big_opL_nil right_id. Qed.
  Lemma big_opL_app f l1 l2 :
    ([ list] ky  l1 ++ l2, f k y)
     ([ list] ky  l1, f k y)  ([ list] ky  l2, f (length l1 + k) y).
  Proof. by rewrite /big_opL imap_app big_op_app. Qed.

  Lemma big_opL_forall R f g l :
    Reflexive R  Proper (R ==> R ==> R) (@op M _) 
    ( k y, l !! k = Some y  R (f k y) (g k y)) 
    R ([ list] k  y  l, f k y) ([ list] k  y  l, g k y).
  Proof.
    intros ? Hop. revert f g. induction l as [|x l IH]=> f g Hf; [done|].
    rewrite !big_opL_cons. apply Hop; eauto.
  Qed.

146
147
148
  Lemma big_opL_mono f g l :
    ( k y, l !! k = Some y  f k y  g k y) 
    ([ list] k  y  l, f k y)  [ list] k  y  l, g k y.
149
  Proof. apply big_opL_forall; apply _. Qed.
150
151
152
153
  Lemma big_opL_ext f g l :
    ( k y, l !! k = Some y  f k y = g k y) 
    ([ list] k  y  l, f k y) = [ list] k  y  l, g k y.
  Proof. apply big_opL_forall; apply _. Qed.
154
155
156
  Lemma big_opL_proper f g l :
    ( k y, l !! k = Some y  f k y  g k y) 
    ([ list] k  y  l, f k y)  ([ list] k  y  l, g k y).
157
  Proof. apply big_opL_forall; apply _. Qed.
158
159
  Lemma big_opL_permutation (f : A  M) l1 l2 :
    l1  l2  ([ list] x  l1, f x)  ([ list] x  l2, f x).
160
  Proof. intros Hl. by rewrite /big_opL !imap_const Hl. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
161
162
163
  Lemma big_opL_submseteq (f : A  M) l1 l2 :
    l1 + l2  ([ list] x  l1, f x)  ([ list] x  l2, f x).
  Proof. intros Hl. apply big_op_submseteq. rewrite !imap_const. by rewrite ->Hl. Qed.
164
165
166
167

  Global Instance big_opL_ne l n :
    Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (dist n))
           (big_opL (M:=M) l).
168
  Proof. intros f g Hf. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
169
170
171
  Global Instance big_opL_proper' l :
    Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
           (big_opL (M:=M) l).
172
  Proof. intros f g Hf. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
173
174
175
  Global Instance big_opL_mono' l :
    Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
           (big_opL (M:=M) l).
176
  Proof. intros f g Hf. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
177

178
179
180
181
182
183
184
  Lemma big_opL_consZ_l (f : Z  A  M) x l :
    ([ list] ky  x :: l, f k y) = f 0 x  [ list] ky  l, f (1 + k)%Z y.
  Proof. rewrite big_opL_cons. auto using big_opL_ext with f_equal lia. Qed.
  Lemma big_opL_consZ_r (f : Z  A  M) x l :
    ([ list] ky  x :: l, f k y) = f 0 x  [ list] ky  l, f (k + 1)%Z y.
  Proof. rewrite big_opL_cons. auto using big_opL_ext with f_equal lia. Qed.

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
  Lemma big_opL_lookup f l i x :
    l !! i = Some x  f i x  [ list] ky  l, f k y.
  Proof.
    intros. rewrite -(take_drop_middle l i x) // big_opL_app big_opL_cons.
    rewrite Nat.add_0_r take_length_le; eauto using lookup_lt_Some, Nat.lt_le_incl.
    eapply transitivity, cmra_included_r; eauto using cmra_included_l.
  Qed.

  Lemma big_opL_elem_of (f : A  M) l x : x  l  f x  [ list] y  l, f y.
  Proof.
    intros [i ?]%elem_of_list_lookup; eauto using (big_opL_lookup (λ _, f)).
  Qed.

  Lemma big_opL_fmap {B} (h : A  B) (f : nat  B  M) l :
    ([ list] ky  h <$> l, f k y)  ([ list] ky  l, f k (h y)).
  Proof. by rewrite /big_opL imap_fmap. Qed.

  Lemma big_opL_opL f g l :
    ([ list] kx  l, f k x  g k x)
     ([ list] kx  l, f k x)  ([ list] kx  l, g k x).
  Proof.
    revert f g; induction l as [|x l IH]=> f g.
    { by rewrite !big_opL_nil left_id. }
    rewrite !big_opL_cons IH.
    by rewrite -!assoc (assoc _ (g _ _)) [(g _ _  _)]comm -!assoc.
  Qed.
End list.

(** ** Big ops over finite maps *)
Section gmap.
  Context `{Countable K} {A : Type}.
  Implicit Types m : gmap K A.
  Implicit Types f g : K  A  M.

219
220
221
222
223
224
225
226
227
  Lemma big_opM_forall R f g m :
    Reflexive R  Proper (R ==> R ==> R) (@op M _) 
    ( k x, m !! k = Some x  R (f k x) (g k x)) 
    R ([ map] k  x  m, f k x) ([ map] k  x  m, g k x).
  Proof.
    intros ?? Hf. apply (big_op_Forall2 R _ _), Forall2_fmap, Forall_Forall2.
    apply Forall_forall=> -[i x] ? /=. by apply Hf, elem_of_map_to_list.
  Qed.

228
229
230
231
  Lemma big_opM_mono f g m1 m2 :
    m1  m2  ( k x, m2 !! k = Some x  f k x  g k x) 
    ([ map] k  x  m1, f k x)  [ map] k  x  m2, g k x.
  Proof.
232
    intros Hm Hf. trans ([ map] kx  m2, f k x).
Robbert Krebbers's avatar
Robbert Krebbers committed
233
    - by apply big_op_submseteq, fmap_submseteq, map_to_list_submseteq.
234
    - apply big_opM_forall; apply _ || auto.
235
  Qed.
236
237
238
239
  Lemma big_opM_ext f g m :
    ( k x, m !! k = Some x  f k x = g k x) 
    ([ map] k  x  m, f k x) = ([ map] k  x  m, g k x).
  Proof. apply big_opM_forall; apply _. Qed.
240
241
242
  Lemma big_opM_proper f g m :
    ( k x, m !! k = Some x  f k x  g k x) 
    ([ map] k  x  m, f k x)  ([ map] k  x  m, g k x).
243
  Proof. apply big_opM_forall; apply _. Qed.
244
245
246
247

  Global Instance big_opM_ne m n :
    Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (dist n))
           (big_opM (M:=M) m).
248
  Proof. intros f g Hf. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
249
250
251
  Global Instance big_opM_proper' m :
    Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
           (big_opM (M:=M) m).
252
  Proof. intros f g Hf. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
253
254
255
  Global Instance big_opM_mono' m :
    Proper (pointwise_relation _ (pointwise_relation _ ()) ==> ())
           (big_opM (M:=M) m).
256
  Proof. intros f g Hf. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

  Lemma big_opM_empty f : ([ map] kx  , f k x) = .
  Proof. by rewrite /big_opM map_to_list_empty. Qed.

  Lemma big_opM_insert f m i x :
    m !! i = None 
    ([ map] ky  <[i:=x]> m, f k y)  f i x  [ map] ky  m, f k y.
  Proof. intros ?. by rewrite /big_opM map_to_list_insert. Qed.

  Lemma big_opM_delete f m i x :
    m !! i = Some x 
    ([ map] ky  m, f k y)  f i x  [ map] ky  delete i m, f k y.
  Proof.
    intros. rewrite -big_opM_insert ?lookup_delete //.
    by rewrite insert_delete insert_id.
  Qed.

  Lemma big_opM_lookup f m i x :
    m !! i = Some x  f i x  [ map] ky  m, f k y.
  Proof. intros. rewrite big_opM_delete //. apply cmra_included_l. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
277
278
279
  Lemma big_opM_lookup_dom (f : K  M) m i :
    is_Some (m !! i)  f i  [ map] k_  m, f k.
  Proof. intros [x ?]. by eapply (big_opM_lookup (λ i x, f i)). Qed.
280
281
282
283
284
285
286
287
288
289
290
291
292
293

  Lemma big_opM_singleton f i x : ([ map] ky  {[i:=x]}, f k y)  f i x.
  Proof.
    rewrite -insert_empty big_opM_insert/=; last auto using lookup_empty.
    by rewrite big_opM_empty right_id.
  Qed.

  Lemma big_opM_fmap {B} (h : A  B) (f : K  B  M) m :
    ([ map] ky  h <$> m, f k y)  ([ map] ky  m, f k (h y)).
  Proof.
    rewrite /big_opM map_to_list_fmap -list_fmap_compose.
    f_equiv; apply reflexive_eq, list_fmap_ext. by intros []. done.
  Qed.

Robbert Krebbers's avatar
Robbert Krebbers committed
294
295
296
  Lemma big_opM_insert_override (f : K  A  M) m i x x' :
    m !! i = Some x  f i x  f i x' 
    ([ map] ky  <[i:=x']> m, f k y)  ([ map] ky  m, f k y).
297
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
298
299
    intros ? Hx. rewrite -insert_delete big_opM_insert ?lookup_delete //.
    by rewrite -Hx -big_opM_delete.
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  Qed.

  Lemma big_opM_fn_insert {B} (g : K  A  B  M) (f : K  B) m i (x : A) b :
    m !! i = None 
      ([ map] ky  <[i:=x]> m, g k y (<[i:=b]> f k))
     (g i x b  [ map] ky  m, g k y (f k)).
  Proof.
    intros. rewrite big_opM_insert // fn_lookup_insert.
    apply cmra_op_proper', big_opM_proper; auto=> k y ?.
    by rewrite fn_lookup_insert_ne; last set_solver.
  Qed.
  Lemma big_opM_fn_insert' (f : K  M) m i x P :
    m !! i = None 
    ([ map] ky  <[i:=x]> m, <[i:=P]> f k)  (P  [ map] ky  m, f k).
  Proof. apply (big_opM_fn_insert (λ _ _, id)). Qed.

  Lemma big_opM_opM f g m :
Robbert Krebbers's avatar
Robbert Krebbers committed
317
    ([ map] kx  m, f k x  g k x)
318
319
     ([ map] kx  m, f k x)  ([ map] kx  m, g k x).
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
320
321
322
323
    induction m as [|i x ?? IH] using map_ind.
    { by rewrite !big_opM_empty left_id. }
    rewrite !big_opM_insert // IH.
    by rewrite -!assoc (assoc _ (g _ _)) [(g _ _  _)]comm -!assoc.
324
325
326
327
328
329
330
331
332
333
  Qed.
End gmap.


(** ** Big ops over finite sets *)
Section gset.
  Context `{Countable A}.
  Implicit Types X : gset A.
  Implicit Types f : A  M.

334
335
336
337
338
339
340
341
342
  Lemma big_opS_forall R f g X :
    Reflexive R  Proper (R ==> R ==> R) (@op M _) 
    ( x, x  X  R (f x) (g x)) 
    R ([ set] x  X, f x) ([ set] x  X, g x).
  Proof.
    intros ?? Hf. apply (big_op_Forall2 R _ _), Forall2_fmap, Forall_Forall2.
    apply Forall_forall=> x ? /=. by apply Hf, elem_of_elements.
  Qed.

343
344
345
346
347
  Lemma big_opS_mono f g X Y :
    X  Y  ( x, x  Y  f x  g x) 
    ([ set] x  X, f x)  [ set] x  Y, g x.
  Proof.
    intros HX Hf. trans ([ set] x  Y, f x).
Robbert Krebbers's avatar
Robbert Krebbers committed
348
    - by apply big_op_submseteq, fmap_submseteq, elements_submseteq.
349
    - apply big_opS_forall; apply _ || auto.
350
  Qed.
351
352
353
354
355
356
357
358
  Lemma big_opS_ext f g X :
    ( x, x  X  f x = g x) 
    ([ set] x  X, f x) = ([ set] x  X, g x).
  Proof. apply big_opS_forall; apply _. Qed.
  Lemma big_opS_proper f g X :
    ( x, x  X  f x  g x) 
    ([ set] x  X, f x)  ([ set] x  X, g x).
  Proof. apply big_opS_forall; apply _. Qed.
359

360
  Global Instance big_opS_ne X n :
361
    Proper (pointwise_relation _ (dist n) ==> dist n) (big_opS (M:=M) X).
362
  Proof. intros f g Hf. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
363
  Global Instance big_opS_proper' X :
364
    Proper (pointwise_relation _ () ==> ()) (big_opS (M:=M) X).
365
  Proof. intros f g Hf. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
366
  Global Instance big_opS_mono' X :
367
    Proper (pointwise_relation _ () ==> ()) (big_opS (M:=M) X).
368
  Proof. intros f g Hf. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
369
370
371
372
373
374
375
376
377
378
379
380
381

  Lemma big_opS_empty f : ([ set] x  , f x) = .
  Proof. by rewrite /big_opS elements_empty. Qed.

  Lemma big_opS_insert f X x :
    x  X  ([ set] y  {[ x ]}  X, f y)  (f x  [ set] y  X, f y).
  Proof. intros. by rewrite /big_opS elements_union_singleton. Qed.
  Lemma big_opS_fn_insert {B} (f : A  B  M) h X x b :
    x  X 
       ([ set] y  {[ x ]}  X, f y (<[x:=b]> h y))
     (f x b  [ set] y  X, f y (h y)).
  Proof.
    intros. rewrite big_opS_insert // fn_lookup_insert.
382
    apply cmra_op_proper', big_opS_proper; auto=> y ?.
383
384
385
386
387
388
    by rewrite fn_lookup_insert_ne; last set_solver.
  Qed.
  Lemma big_opS_fn_insert' f X x P :
    x  X  ([ set] y  {[ x ]}  X, <[x:=P]> f y)  (P  [ set] y  X, f y).
  Proof. apply (big_opS_fn_insert (λ y, id)). Qed.

Robbert Krebbers's avatar
Robbert Krebbers committed
389
390
391
392
393
394
395
396
397
398
  Lemma big_opS_union f X Y :
    X  Y 
    ([ set] y  X  Y, f y)  ([ set] y  X, f y)  ([ set] y  Y, f y).
  Proof.
    intros. induction X as [|x X ? IH] using collection_ind_L.
    { by rewrite left_id_L big_opS_empty left_id. }
    rewrite -assoc_L !big_opS_insert; [|set_solver..].
    by rewrite -assoc IH; last set_solver.
  Qed.

399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  Lemma big_opS_delete f X x :
    x  X  ([ set] y  X, f y)  f x  [ set] y  X  {[ x ]}, f y.
  Proof.
    intros. rewrite -big_opS_insert; last set_solver.
    by rewrite -union_difference_L; last set_solver.
  Qed.

  Lemma big_opS_elem_of f X x : x  X  f x  [ set] y  X, f y.
  Proof. intros. rewrite big_opS_delete //. apply cmra_included_l. Qed.

  Lemma big_opS_singleton f x : ([ set] y  {[ x ]}, f y)  f x.
  Proof. intros. by rewrite /big_opS elements_singleton /= right_id. Qed.

  Lemma big_opS_opS f g X :
    ([ set] y  X, f y  g y)  ([ set] y  X, f y)  ([ set] y  X, g y).
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
415
416
417
418
    induction X as [|x X ? IH] using collection_ind_L.
    { by rewrite !big_opS_empty left_id. }
    rewrite !big_opS_insert // IH.
    by rewrite -!assoc (assoc _ (g _)) [(g _  _)]comm -!assoc.
419
420
  Qed.
End gset.
Robbert Krebbers's avatar
Robbert Krebbers committed
421

Robbert Krebbers's avatar
Robbert Krebbers committed
422
423
424
425
426
427
Lemma big_opM_dom `{Countable K} {A} (f : K  M) (m : gmap K A) :
  ([ map] k_  m, f k)  ([ set] k  dom _ m, f k).
Proof.
  induction m as [|i x ?? IH] using map_ind; [by rewrite dom_empty_L|].
  by rewrite dom_insert_L big_opM_insert // IH big_opS_insert ?not_elem_of_dom.
Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448

(** ** Big ops over finite msets *)
Section gmultiset.
  Context `{Countable A}.
  Implicit Types X : gmultiset A.
  Implicit Types f : A  M.

  Lemma big_opMS_forall R f g X :
    Reflexive R  Proper (R ==> R ==> R) (@op M _) 
    ( x, x  X  R (f x) (g x)) 
    R ([ mset] x  X, f x) ([ mset] x  X, g x).
  Proof.
    intros ?? Hf. apply (big_op_Forall2 R _ _), Forall2_fmap, Forall_Forall2.
    apply Forall_forall=> x ? /=. by apply Hf, gmultiset_elem_of_elements.
  Qed.

  Lemma big_opMS_mono f g X Y :
    X  Y  ( x, x  Y  f x  g x) 
    ([ mset] x  X, f x)  [ mset] x  Y, g x.
  Proof.
    intros HX Hf. trans ([ mset] x  Y, f x).
Robbert Krebbers's avatar
Robbert Krebbers committed
449
    - by apply big_op_submseteq, fmap_submseteq, gmultiset_elements_submseteq.
Robbert Krebbers's avatar
Robbert Krebbers committed
450
451
452
453
454
455
456
457
458
459
460
    - apply big_opMS_forall; apply _ || auto.
  Qed.
  Lemma big_opMS_ext f g X :
    ( x, x  X  f x = g x) 
    ([ mset] x  X, f x) = ([ mset] x  X, g x).
  Proof. apply big_opMS_forall; apply _. Qed.
  Lemma big_opMS_proper f g X :
    ( x, x  X  f x  g x) 
    ([ mset] x  X, f x)  ([ mset] x  X, g x).
  Proof. apply big_opMS_forall; apply _. Qed.

461
  Global Instance big_opMS_ne X n :
Robbert Krebbers's avatar
Robbert Krebbers committed
462
463
    Proper (pointwise_relation _ (dist n) ==> dist n) (big_opMS (M:=M) X).
  Proof. intros f g Hf. apply big_opMS_forall; apply _ || intros; apply Hf. Qed.
464
  Global Instance big_opMS_proper' X :
Robbert Krebbers's avatar
Robbert Krebbers committed
465
466
    Proper (pointwise_relation _ () ==> ()) (big_opMS (M:=M) X).
  Proof. intros f g Hf. apply big_opMS_forall; apply _ || intros; apply Hf. Qed.
467
  Global Instance big_opMS_mono' X :
Robbert Krebbers's avatar
Robbert Krebbers committed
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
    Proper (pointwise_relation _ () ==> ()) (big_opMS (M:=M) X).
  Proof. intros f g Hf. apply big_opMS_forall; apply _ || intros; apply Hf. Qed.

  Lemma big_opMS_empty f : ([ mset] x  , f x) = .
  Proof. by rewrite /big_opMS gmultiset_elements_empty. Qed.

  Lemma big_opMS_union f X Y :
    ([ mset] y  X  Y, f y)  ([ mset] y  X, f y)  [ mset] y  Y, f y.
  Proof. by rewrite /big_opMS gmultiset_elements_union fmap_app big_op_app. Qed.

  Lemma big_opMS_singleton f x : ([ mset] y  {[ x ]}, f y)  f x.
  Proof.
    intros. by rewrite /big_opMS gmultiset_elements_singleton /= right_id.
  Qed.

Robbert Krebbers's avatar
Robbert Krebbers committed
483
484
485
  Lemma big_opMS_delete f X x :
    x  X  ([ mset] y  X, f y)  f x  [ mset] y  X  {[ x ]}, f y.
  Proof.
486
487
    intros. rewrite -big_opMS_singleton -big_opMS_union.
    by rewrite -gmultiset_union_difference'.
Robbert Krebbers's avatar
Robbert Krebbers committed
488
489
490
491
492
  Qed.

  Lemma big_opMS_elem_of f X x : x  X  f x  [ mset] y  X, f y.
  Proof. intros. rewrite big_opMS_delete //. apply cmra_included_l. Qed.

493
  Lemma big_opMS_opMS f g X :
Robbert Krebbers's avatar
Robbert Krebbers committed
494
495
    ([ mset] y  X, f y  g y)  ([ mset] y  X, f y)  ([ mset] y  X, g y).
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
496
497
498
499
    induction X as [|x X IH] using gmultiset_ind.
    { by rewrite !big_opMS_empty left_id. }
    rewrite !big_opMS_union !big_opMS_singleton IH.
    by rewrite -!assoc (assoc _ (g _)) [(g _  _)]comm -!assoc.
Robbert Krebbers's avatar
Robbert Krebbers committed
500
501
  Qed.
End gmultiset.
502
End big_op.
503

Robbert Krebbers's avatar
Robbert Krebbers committed
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
(** Option *)
Lemma big_opL_None {M : cmraT} {A} (f : nat  A  option M) l :
  ([ list] kx  l, f k x) = None   k x, l !! k = Some x  f k x = None.
Proof.
  revert f. induction l as [|x l IH]=> f //=.
  rewrite big_opL_cons op_None IH. split.
  - intros [??] [|k] y ?; naive_solver.
  - intros Hl. split. by apply (Hl 0). intros k. apply (Hl (S k)).
Qed.
Lemma big_opM_None {M : cmraT} `{Countable K} {A} (f : K  A  option M) m :
  ([ map] kx  m, f k x) = None   k x, m !! k = Some x  f k x = None.
Proof.
  induction m as [|i x m ? IH] using map_ind=> //=.
  rewrite -equiv_None big_opM_insert // equiv_None op_None IH. split.
  { intros [??] k y. rewrite lookup_insert_Some; naive_solver. }
  intros Hm; split.
  - apply (Hm i). by simplify_map_eq.
  - intros k y ?. apply (Hm k). by simplify_map_eq.
Qed.
Lemma big_opS_None {M : cmraT} `{Countable A} (f : A  option M) X :
  ([ set] x  X, f x) = None   x, x  X  f x = None.
Proof.
  induction X as [|x X ? IH] using collection_ind_L; [done|].
  rewrite -equiv_None big_opS_insert // equiv_None op_None IH. set_solver.
Qed.
529
530
531
532
533
534
535
536
Lemma big_opMS_None {M : cmraT} `{Countable A} (f : A  option M) X :
  ([ mset] x  X, f x) = None   x, x  X  f x = None.
Proof.
  induction X as [|x X IH] using gmultiset_ind.
  { rewrite big_opMS_empty. set_solver. }
  rewrite -equiv_None big_opMS_union big_opMS_singleton equiv_None op_None IH.
  set_solver.
Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
537
538

(** Commuting with respect to homomorphisms *)
539
Lemma big_opL_commute {M1 M2 : ucmraT} {A} (h : M1  M2)
540
    `{!UCMRAHomomorphism h} (f : nat  A  M1) l :
541
542
  h ([ list] kx  l, f k x)  ([ list] kx  l, h (f k x)).
Proof.
543
544
545
  revert f. induction l as [|x l IH]=> f.
  - by rewrite !big_opL_nil ucmra_homomorphism_unit.
  - by rewrite !big_opL_cons cmra_homomorphism -IH.
546
547
Qed.
Lemma big_opL_commute1 {M1 M2 : ucmraT} {A} (h : M1  M2)
548
549
    `{!CMRAHomomorphism h} (f : nat  A  M1) l :
  l  []  h ([ list] kx  l, f k x)  ([ list] kx  l, h (f k x)).
550
Proof.
551
  intros ?. revert f. induction l as [|x [|x' l'] IH]=> f //.
552
  - by rewrite !big_opL_singleton.
553
  - by rewrite !(big_opL_cons _ x) cmra_homomorphism -IH.
554
555
556
Qed.

Lemma big_opM_commute {M1 M2 : ucmraT} `{Countable K} {A} (h : M1  M2)
557
    `{!UCMRAHomomorphism h} (f : K  A  M1) m :
558
559
  h ([ map] kx  m, f k x)  ([ map] kx  m, h (f k x)).
Proof.
560
561
562
  intros. induction m as [|i x m ? IH] using map_ind.
  - by rewrite !big_opM_empty ucmra_homomorphism_unit.
  - by rewrite !big_opM_insert // cmra_homomorphism -IH.
563
564
Qed.
Lemma big_opM_commute1 {M1 M2 : ucmraT} `{Countable K} {A} (h : M1  M2)
565
566
    `{!CMRAHomomorphism h} (f : K  A  M1) m :
  m    h ([ map] kx  m, f k x)  ([ map] kx  m, h (f k x)).
567
Proof.
568
569
570
571
  intros. induction m as [|i x m ? IH] using map_ind; [done|].
  destruct (decide (m = )) as [->|].
  - by rewrite !big_opM_insert // !big_opM_empty !right_id.
  - by rewrite !big_opM_insert // cmra_homomorphism -IH //.
572
573
Qed.

574
575
Lemma big_opS_commute {M1 M2 : ucmraT} `{Countable A}
    (h : M1  M2) `{!UCMRAHomomorphism h} (f : A  M1) X :
576
577
  h ([ set] x  X, f x)  ([ set] x  X, h (f x)).
Proof.
578
579
580
  intros. induction X as [|x X ? IH] using collection_ind_L.
  - by rewrite !big_opS_empty ucmra_homomorphism_unit.
  - by rewrite !big_opS_insert // cmra_homomorphism -IH.
581
Qed.
582
583
584
Lemma big_opS_commute1 {M1 M2 : ucmraT} `{Countable A}
    (h : M1  M2) `{!CMRAHomomorphism h} (f : A  M1) X :
  X    h ([ set] x  X, f x)  ([ set] x  X, h (f x)).
585
Proof.
586
587
588
589
  intros. induction X as [|x X ? IH] using collection_ind_L; [done|].
  destruct (decide (X = )) as [->|].
  - by rewrite !big_opS_insert // !big_opS_empty !right_id.
  - by rewrite !big_opS_insert // cmra_homomorphism -IH //.
590
Qed.
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
Lemma big_opMS_commute {M1 M2 : ucmraT} `{Countable A}
    (h : M1  M2) `{!UCMRAHomomorphism h} (f : A  M1) X :
  h ([ mset] x  X, f x)  ([ mset] x  X, h (f x)).
Proof.
  intros. induction X as [|x X IH] using gmultiset_ind.
  - by rewrite !big_opMS_empty ucmra_homomorphism_unit.
  - by rewrite !big_opMS_union !big_opMS_singleton cmra_homomorphism -IH.
Qed.
Lemma big_opMS_commute1 {M1 M2 : ucmraT} `{Countable A}
    (h : M1  M2) `{!CMRAHomomorphism h} (f : A  M1) X :
  X    h ([ mset] x  X, f x)  ([ mset] x  X, h (f x)).
Proof.
  intros. induction X as [|x X IH] using gmultiset_ind; [done|].
  destruct (decide (X = )) as [->|].
  - by rewrite !big_opMS_union !big_opMS_singleton !big_opMS_empty !right_id.
  - by rewrite !big_opMS_union !big_opMS_singleton cmra_homomorphism -IH //.
Qed.

610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
Lemma big_opL_commute_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2} {A}
    (h : M1  M2) `{!UCMRAHomomorphism h} (f : nat  A  M1) l :
  h ([ list] kx  l, f k x) = ([ list] kx  l, h (f k x)).
Proof. unfold_leibniz. by apply big_opL_commute. Qed.
Lemma big_opL_commute1_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2} {A}
    (h : M1  M2) `{!CMRAHomomorphism h} (f : nat  A  M1) l :
  l  []  h ([ list] kx  l, f k x) = ([ list] kx  l, h (f k x)).
Proof. unfold_leibniz. by apply big_opL_commute1. Qed.

Lemma big_opM_commute_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable K} {A}
    (h : M1  M2) `{!UCMRAHomomorphism h} (f : K  A  M1) m :
  h ([ map] kx  m, f k x) = ([ map] kx  m, h (f k x)).
Proof. unfold_leibniz. by apply big_opM_commute. Qed.
Lemma big_opM_commute1_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable K} {A}
    (h : M1  M2) `{!CMRAHomomorphism h} (f : K  A  M1) m :
  m    h ([ map] kx  m, f k x) = ([ map] kx  m, h (f k x)).
Proof. unfold_leibniz. by apply big_opM_commute1. Qed.

Lemma big_opS_commute_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable A}
    (h : M1  M2) `{!UCMRAHomomorphism h} (f : A  M1) X :
  h ([ set] x  X, f x) = ([ set] x  X, h (f x)).
Proof. unfold_leibniz. by apply big_opS_commute. Qed.
Lemma big_opS_commute1_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable A}
    (h : M1  M2) `{!CMRAHomomorphism h} (f : A  M1) X :
  X    h ([ set] x  X, f x) = ([ set] x  X, h (f x)).
Proof. intros. rewrite <-leibniz_equiv_iff. by apply big_opS_commute1. Qed.
636
637
638
639
640
641
642
643
644

Lemma big_opMS_commute_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable A}
    (h : M1  M2) `{!UCMRAHomomorphism h} (f : A  M1) X :
  h ([ mset] x  X, f x) = ([ mset] x  X, h (f x)).
Proof. unfold_leibniz. by apply big_opMS_commute. Qed.
Lemma big_opMS_commute1_L {M1 M2 : ucmraT} `{!LeibnizEquiv M2, Countable A}
    (h : M1  M2) `{!CMRAHomomorphism h} (f : A  M1) X :
  X    h ([ mset] x  X, f x) = ([ mset] x  X, h (f x)).
Proof. intros. rewrite <-leibniz_equiv_iff. by apply big_opMS_commute1. Qed.