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

4 5 6 7 8 9 10 11 12
(** 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
13
- The operator [ [⋅ set] x ∈ X, P ] folds over a set [X]. The binder [x] refers
14 15 16 17 18 19 20 21
  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 :=
22
  match xs with [] =>  | x :: xs => x  big_op xs end.
23 24
Arguments big_op _ !_ /.
Instance: Params (@big_op) 1.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
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.
47 48 49
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.
50 51 52 53 54 55 56 57

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.
58

Robbert Krebbers's avatar
Robbert Krebbers committed
59 60 61 62 63 64 65 66
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.

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

(** * Big ops *)
73 74 75 76 77
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.

78
Global Instance big_op_ne n : Proper (dist n ==> dist n) (@big_op M).
79
Proof. apply big_op_Forall2; apply _. Qed.
80 81 82
Global Instance big_op_proper : Proper (() ==> ()) (@big_op M) := ne_proper _.

Lemma big_op_nil : [] (@nil M) = .
83
Proof. done. Qed.
84
Lemma big_op_cons x xs : [] (x :: xs) = x  [] xs.
85
Proof. done. Qed.
86 87 88 89 90 91 92 93 94 95
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).
96 97
Proof.
  induction 1 as [|x xs1 xs2 ? IH|x y xs|xs1 xs2 xs3]; simpl; auto.
98 99
  - by rewrite IH.
  - by rewrite !assoc (comm _ x).
100
  - by trans (big_op xs2).
101
Qed.
102 103

Lemma big_op_contains xs ys : xs `contains` ys  [] xs  [] ys.
104
Proof.
105 106
  intros [xs' ->]%contains_Permutation.
  rewrite big_op_app; apply cmra_included_l.
107
Qed.
108 109

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

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

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

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
  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.

145 146 147
  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.
148
  Proof. apply big_opL_forall; apply _. Qed.
149 150 151 152
  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.
153 154 155
  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).
156
  Proof. apply big_opL_forall; apply _. Qed.
157 158
  Lemma big_opL_permutation (f : A  M) l1 l2 :
    l1  l2  ([ list] x  l1, f x)  ([ list] x  l2, f x).
159
  Proof. intros Hl. by rewrite /big_opL !imap_const Hl. Qed.
160 161 162
  Lemma big_opL_contains (f : A  M) l1 l2 :
    l1 `contains` l2  ([ list] x  l1, f x)  ([ list] x  l2, f x).
  Proof. intros Hl. apply big_op_contains. rewrite !imap_const. by rewrite ->Hl. Qed.
163 164 165 166

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

177 178 179 180 181 182 183
  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.

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
  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.

218 219 220 221 222 223 224 225 226
  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.

227 228 229 230
  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.
231
    intros Hm Hf. trans ([ map] kx  m2, f k x).
232
    - by apply big_op_contains, fmap_contains, map_to_list_contains.
233
    - apply big_opM_forall; apply _ || auto.
234
  Qed.
235 236 237 238
  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.
239 240 241
  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).
242
  Proof. apply big_opM_forall; apply _. Qed.
243 244 245 246

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

  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
276 277 278
  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.
279 280 281 282 283 284 285 286 287 288 289 290 291 292

  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
293 294 295
  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).
296
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
297 298
    intros ? Hx. rewrite -insert_delete big_opM_insert ?lookup_delete //.
    by rewrite -Hx -big_opM_delete.
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
  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
316
    ([ map] kx  m, f k x  g k x)
317 318
     ([ map] kx  m, f k x)  ([ map] kx  m, g k x).
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
319 320 321 322
    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.
323 324 325 326 327 328 329 330 331 332
  Qed.
End gmap.


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

333 334 335 336 337 338 339 340 341
  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.

342 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).
    - by apply big_op_contains, fmap_contains, elements_contains.
348
    - apply big_opS_forall; apply _ || auto.
349
  Qed.
350 351 352 353 354 355 356 357
  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.
358

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

  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.
381
    apply cmra_op_proper', big_opS_proper; auto=> y ?.
382 383 384 385 386 387
    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
388 389 390 391 392 393 394 395 396 397
  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.

398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
  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
414 415 416 417
    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.
418 419
  Qed.
End gset.
Robbert Krebbers's avatar
Robbert Krebbers committed
420

Robbert Krebbers's avatar
Robbert Krebbers committed
421 422 423 424 425 426
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
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459

(** ** 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).
    - by apply big_op_contains, fmap_contains, gmultiset_elements_contains.
    - 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.

460
  Global Instance big_opMS_ne X n :
Robbert Krebbers's avatar
Robbert Krebbers committed
461 462
    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.
463
  Global Instance big_opMS_proper' X :
Robbert Krebbers's avatar
Robbert Krebbers committed
464 465
    Proper (pointwise_relation _ () ==> ()) (big_opMS (M:=M) X).
  Proof. intros f g Hf. apply big_opMS_forall; apply _ || intros; apply Hf. Qed.
466
  Global Instance big_opMS_mono' X :
Robbert Krebbers's avatar
Robbert Krebbers committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
    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
482 483 484
  Lemma big_opMS_delete f X x :
    x  X  ([ mset] y  X, f y)  f x  [ mset] y  X  {[ x ]}, f y.
  Proof.
485 486
    intros. rewrite -big_opMS_singleton -big_opMS_union.
    by rewrite -gmultiset_union_difference'.
Robbert Krebbers's avatar
Robbert Krebbers committed
487 488 489 490 491
  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.

492
  Lemma big_opMS_opMS f g X :
Robbert Krebbers's avatar
Robbert Krebbers committed
493 494
    ([ 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
495 496 497 498
    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
499 500
  Qed.
End gmultiset.
501
End big_op.
502

Robbert Krebbers's avatar
Robbert Krebbers committed
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
(** 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.
528 529 530 531 532 533 534 535
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
536 537

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

Lemma big_opM_commute {M1 M2 : ucmraT} `{Countable K} {A} (h : M1  M2)
556
    `{!UCMRAHomomorphism h} (f : K  A  M1) m :
557 558
  h ([ map] kx  m, f k x)  ([ map] kx  m, h (f k x)).
Proof.
559 560 561
  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.
562 563
Qed.
Lemma big_opM_commute1 {M1 M2 : ucmraT} `{Countable K} {A} (h : M1  M2)
564 565
    `{!CMRAHomomorphism h} (f : K  A  M1) m :
  m    h ([ map] kx  m, f k x)  ([ map] kx  m, h (f k x)).
566
Proof.
567 568 569 570
  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 //.
571 572
Qed.

573 574
Lemma big_opS_commute {M1 M2 : ucmraT} `{Countable A}
    (h : M1  M2) `{!UCMRAHomomorphism h} (f : A  M1) X :
575 576
  h ([ set] x  X, f x)  ([ set] x  X, h (f x)).
Proof.
577 578 579
  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.
580
Qed.
581 582 583
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)).
584
Proof.
585 586 587 588
  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 //.
589
Qed.
590

591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
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.

609 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
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.
635 636 637 638 639 640 641 642 643

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.