big_op.v 134 KB
Newer Older
Robbert Krebbers's avatar
Robbert Krebbers committed
1
From stdpp Require Import countable fin_sets functions.
2
From iris.algebra Require Export big_op.
3
4
From iris.algebra Require Import list gmap.
From iris.bi Require Import derived_laws_later.
Ralf Jung's avatar
Ralf Jung committed
5
From iris.prelude Require Import options.
6
Import interface.bi derived_laws.bi derived_laws_later.bi.
7

Dan Frumin's avatar
Dan Frumin committed
8
(** Notations for unary variants *)
Ralf Jung's avatar
Ralf Jung committed
9
Notation "'[∗' 'list]' k ↦ x ∈ l , P" :=
Ralf Jung's avatar
Ralf Jung committed
10
  (big_opL bi_sep (λ k x, P%I) l) : bi_scope.
Ralf Jung's avatar
Ralf Jung committed
11
Notation "'[∗' 'list]' x ∈ l , P" :=
Ralf Jung's avatar
Ralf Jung committed
12
13
  (big_opL bi_sep (λ _ x, P%I) l) : bi_scope.
Notation "'[∗]' Ps" := (big_opL bi_sep (λ _ x, x) Ps%I) : bi_scope.
Ralf Jung's avatar
Ralf Jung committed
14
15

Notation "'[∧' 'list]' k ↦ x ∈ l , P" :=
Ralf Jung's avatar
Ralf Jung committed
16
  (big_opL bi_and (λ k x, P%I) l) : bi_scope.
Ralf Jung's avatar
Ralf Jung committed
17
Notation "'[∧' 'list]' x ∈ l , P" :=
Ralf Jung's avatar
Ralf Jung committed
18
19
  (big_opL bi_and (λ _ x, P%I) l) : bi_scope.
Notation "'[∧]' Ps" := (big_opL bi_and (λ _ x, x) Ps%I) : bi_scope.
Ralf Jung's avatar
Ralf Jung committed
20

21
Notation "'[∨' 'list]' k ↦ x ∈ l , P" :=
Ralf Jung's avatar
Ralf Jung committed
22
  (big_opL bi_or (λ k x, P%I) l) : bi_scope.
23
Notation "'[∨' 'list]' x ∈ l , P" :=
Ralf Jung's avatar
Ralf Jung committed
24
25
  (big_opL bi_or (λ _ x, P%I) l) : bi_scope.
Notation "'[∨]' Ps" := (big_opL bi_or (λ _ x, x) Ps%I) : bi_scope.
26

Ralf Jung's avatar
Ralf Jung committed
27
28
Notation "'[∗' 'map]' k ↦ x ∈ m , P" := (big_opM bi_sep (λ k x, P%I) m) : bi_scope.
Notation "'[∗' 'map]' x ∈ m , P" := (big_opM bi_sep (λ _ x, P%I) m) : bi_scope.
Ralf Jung's avatar
Ralf Jung committed
29

Michael Sammler's avatar
Michael Sammler committed
30
31
32
Notation "'[∧' 'map]' k ↦ x ∈ m , P" := (big_opM bi_and (λ k x, P) m) : bi_scope.
Notation "'[∧' 'map]' x ∈ m , P" := (big_opM bi_and (λ _ x, P) m) : bi_scope.

Ralf Jung's avatar
Ralf Jung committed
33
Notation "'[∗' 'set]' x ∈ X , P" := (big_opS bi_sep (λ x, P%I) X) : bi_scope.
Ralf Jung's avatar
Ralf Jung committed
34

Ralf Jung's avatar
Ralf Jung committed
35
Notation "'[∗' 'mset]' x ∈ X , P" := (big_opMS bi_sep (λ x, P%I) X) : bi_scope.
36

Dan Frumin's avatar
Dan Frumin committed
37
38
39
40
41
42
43
44
45
46
47
48
(** Definitions and notations for binary variants *)
(** A version of the separating big operator that ranges over two lists. This
version also ensures that both lists have the same length. Although this version
can be defined in terms of the unary using a [zip] (see [big_sepL2_alt]), we do
not define it that way to get better computational behavior (for [simpl]). *)
Fixpoint big_sepL2 {PROP : bi} {A B}
    (Φ : nat  A  B  PROP) (l1 : list A) (l2 : list B) : PROP :=
  match l1, l2 with
  | [], [] => emp
  | x1 :: l1, x2 :: l2 => Φ 0 x1 x2  big_sepL2 (λ n, Φ (S n)) l1 l2
  | _, _ => False
  end%I.
49
Global Instance: Params (@big_sepL2) 3 := {}.
Ralf Jung's avatar
Ralf Jung committed
50
Global Arguments big_sepL2 {PROP A B} _ !_ !_ /.
Dan Frumin's avatar
Dan Frumin committed
51
52
Typeclasses Opaque big_sepL2.
Notation "'[∗' 'list]' k ↦ x1 ; x2 ∈ l1 ; l2 , P" :=
Ralf Jung's avatar
Ralf Jung committed
53
  (big_sepL2 (λ k x1 x2, P%I) l1 l2) : bi_scope.
Dan Frumin's avatar
Dan Frumin committed
54
Notation "'[∗' 'list]' x1 ; x2 ∈ l1 ; l2 , P" :=
Ralf Jung's avatar
Ralf Jung committed
55
  (big_sepL2 (λ _ x1 x2, P%I) l1 l2) : bi_scope.
Dan Frumin's avatar
Dan Frumin committed
56

57
Definition big_sepM2_def {PROP : bi} `{Countable K} {A B}
Dan Frumin's avatar
Dan Frumin committed
58
59
60
    (Φ : K  A  B  PROP) (m1 : gmap K A) (m2 : gmap K B) : PROP :=
  (  k, is_Some (m1 !! k)  is_Some (m2 !! k)  
   [ map] k  xy  map_zip m1 m2, Φ k xy.1 xy.2)%I.
61
Definition big_sepM2_aux : seal (@big_sepM2_def). Proof. by eexists. Qed.
62
Definition big_sepM2 := big_sepM2_aux.(unseal).
Ralf Jung's avatar
Ralf Jung committed
63
Global Arguments big_sepM2 {PROP K _ _ A B} _ _ _.
Ralf Jung's avatar
Ralf Jung committed
64
Definition big_sepM2_eq : @big_sepM2 = _ := big_sepM2_aux.(seal_eq).
65
Global Instance: Params (@big_sepM2) 6 := {}.
Dan Frumin's avatar
Dan Frumin committed
66
Notation "'[∗' 'map]' k ↦ x1 ; x2 ∈ m1 ; m2 , P" :=
Ralf Jung's avatar
Ralf Jung committed
67
  (big_sepM2 (λ k x1 x2, P%I) m1 m2) : bi_scope.
Dan Frumin's avatar
Dan Frumin committed
68
Notation "'[∗' 'map]' x1 ; x2 ∈ m1 ; m2 , P" :=
Ralf Jung's avatar
Ralf Jung committed
69
  (big_sepM2 (λ _ x1 x2, P%I) m1 m2) : bi_scope.
Dan Frumin's avatar
Dan Frumin committed
70

71
(** * Properties *)
72
Section big_op.
Robbert Krebbers's avatar
Robbert Krebbers committed
73
Context {PROP : bi}.
74
Implicit Types P Q : PROP.
Robbert Krebbers's avatar
Robbert Krebbers committed
75
Implicit Types Ps Qs : list PROP.
76
77
Implicit Types A : Type.

78
(** ** Big ops over lists *)
79
Section sep_list.
80
81
  Context {A : Type}.
  Implicit Types l : list A.
Robbert Krebbers's avatar
Robbert Krebbers committed
82
  Implicit Types Φ Ψ : nat  A  PROP.
83

Robbert Krebbers's avatar
Robbert Krebbers committed
84
  Lemma big_sepL_nil Φ : ([ list] ky  nil, Φ k y)  emp.
85
  Proof. done. Qed.
86
87
  Lemma big_sepL_nil' P `{!Affine P} Φ : P  [ list] ky  nil, Φ k y.
  Proof. apply: affine. Qed.
88
  Lemma big_sepL_cons Φ x l :
89
    ([ list] ky  x :: l, Φ k y)  Φ 0 x  [ list] ky  l, Φ (S k) y.
90
  Proof. by rewrite big_opL_cons. Qed.
91
  Lemma big_sepL_singleton Φ x : ([ list] ky  [x], Φ k y)  Φ 0 x.
92
93
  Proof. by rewrite big_opL_singleton. Qed.
  Lemma big_sepL_app Φ l1 l2 :
94
95
    ([ list] ky  l1 ++ l2, Φ k y)
     ([ list] ky  l1, Φ k y)  ([ list] ky  l2, Φ (length l1 + k) y).
96
  Proof. by rewrite big_opL_app. Qed.
Ralf Jung's avatar
Ralf Jung committed
97
98
99
  Lemma big_sepL_snoc Φ l x :
    ([ list] ky  l ++ [x], Φ k y)  ([ list] ky  l, Φ k y)  Φ (length l) x.
  Proof. by rewrite big_opL_snoc. Qed.
100

Ralf Jung's avatar
Ralf Jung committed
101
  Lemma big_sepL_take_drop Φ l n :
Ralf Jung's avatar
Ralf Jung committed
102
103
    ([ list] k  x  l, Φ k x) 
    ([ list] k  x  take n l, Φ k x)  ([ list] k  x  drop n l, Φ (n + k) x).
Ralf Jung's avatar
Ralf Jung committed
104
  Proof. by rewrite big_opL_take_drop. Qed.
Ralf Jung's avatar
Ralf Jung committed
105

106
  Lemma big_sepL_submseteq (Φ : A  PROP) `{! x, Affine (Φ x)} l1 l2 :
107
108
    l1 + l2  ([ list] y  l2, Φ y)  [ list] y  l1, Φ y.
  Proof.
109
110
    intros [l ->]%submseteq_Permutation. rewrite big_sepL_app.
    induction l as [|x l IH]; simpl; [by rewrite right_id|by rewrite sep_elim_r].
111
112
113
114
  Qed.

  (** The lemmas [big_sepL_mono], [big_sepL_ne] and [big_sepL_proper] are more
  generic than the instances as they also give [l !! k = Some y] in the premise. *)
115
116
  Lemma big_sepL_mono Φ Ψ l :
    ( k y, l !! k = Some y  Φ k y  Ψ k y) 
117
    ([ list] k  y  l, Φ k y)  [ list] k  y  l, Ψ k y.
118
  Proof. apply big_opL_gen_proper; apply _. Qed.
119
120
121
122
  Lemma big_sepL_ne Φ Ψ l n :
    ( k y, l !! k = Some y  Φ k y {n} Ψ k y) 
    ([ list] k  y  l, Φ k y)%I {n} ([ list] k  y  l, Ψ k y)%I.
  Proof. apply big_opL_ne. Qed.
123
124
  Lemma big_sepL_proper Φ Ψ l :
    ( k y, l !! k = Some y  Φ k y  Ψ k y) 
125
    ([ list] k  y  l, Φ k y)  ([ list] k  y  l, Ψ k y).
126
  Proof. apply big_opL_proper. Qed.
127

128
129
  (** No need to declare instances for non-expansiveness and properness, we
  get both from the generic [big_opL] instances. *)
130
131
  Global Instance big_sepL_mono' :
    Proper (pointwise_relation _ (pointwise_relation _ ()) ==> (=) ==> ())
Robbert Krebbers's avatar
Robbert Krebbers committed
132
           (big_opL (@bi_sep PROP) (A:=A)).
133
  Proof. intros f g Hf m ? <-. apply big_sepL_mono; intros; apply Hf. Qed.
134
  Global Instance big_sepL_id_mono' :
135
    Proper (Forall2 () ==> ()) (big_opL (@bi_sep PROP) (λ _ P, P)).
136
  Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed.
137

Robbert Krebbers's avatar
Robbert Krebbers committed
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
  Global Instance big_sepL_nil_persistent Φ :
    Persistent ([ list] kx  [], Φ k x).
  Proof. simpl; apply _. Qed.
  Global Instance big_sepL_persistent Φ l :
    ( k x, Persistent (Φ k x))  Persistent ([ list] kx  l, Φ k x).
  Proof. revert Φ. induction l as [|x l IH]=> Φ ? /=; apply _. Qed.
  Global Instance big_sepL_persistent_id Ps :
    TCForall Persistent Ps  Persistent ([] Ps).
  Proof. induction 1; simpl; apply _. Qed.

  Global Instance big_sepL_nil_affine Φ :
    Affine ([ list] kx  [], Φ k x).
  Proof. simpl; apply _. Qed.
  Global Instance big_sepL_affine Φ l :
    ( k x, Affine (Φ k x))  Affine ([ list] kx  l, Φ k x).
  Proof. revert Φ. induction l as [|x l IH]=> Φ ? /=; apply _. Qed.
  Global Instance big_sepL_affine_id Ps : TCForall Affine Ps  Affine ([] Ps).
  Proof. induction 1; simpl; apply _. Qed.

  Global Instance big_sepL_nil_timeless `{!Timeless (emp%I : PROP)} Φ :
    Timeless ([ list] kx  [], Φ k x).
  Proof. simpl; apply _. Qed.
  Global Instance big_sepL_timeless `{!Timeless (emp%I : PROP)} Φ l :
    ( k x, Timeless (Φ k x))  Timeless ([ list] kx  l, Φ k x).
  Proof. revert Φ. induction l as [|x l IH]=> Φ ? /=; apply _. Qed.
  Global Instance big_sepL_timeless_id `{!Timeless (emp%I : PROP)} Ps :
    TCForall Timeless Ps  Timeless ([] Ps).
  Proof. induction 1; simpl; apply _. Qed.

167
  Lemma big_sepL_emp l : ([ list] ky  l, emp) @{PROP} emp.
Robbert Krebbers's avatar
Robbert Krebbers committed
168
169
  Proof. by rewrite big_opL_unit. Qed.

170
  Lemma big_sepL_insert_acc Φ l i x :
171
    l !! i = Some x 
172
    ([ list] ky  l, Φ k y)  Φ i x  ( y, Φ i y - ([ list] ky  <[i:=y]>l, Φ k y)).
173
  Proof.
174
175
176
177
178
179
180
181
    intros Hli. assert (i  length l) by eauto using lookup_lt_Some, Nat.lt_le_incl.
    rewrite -(take_drop_middle l i x) // big_sepL_app /=.
    rewrite Nat.add_0_r take_length_le //.
    rewrite assoc -!(comm _ (Φ _ _)) -assoc. apply sep_mono_r, forall_intro=> y.
    rewrite insert_app_r_alt ?take_length_le //.
    rewrite Nat.sub_diag /=. apply wand_intro_l.
    rewrite assoc !(comm _ (Φ _ _)) -assoc big_sepL_app /=.
    by rewrite Nat.add_0_r take_length_le.
182
183
  Qed.

184
185
186
187
188
  Lemma big_sepL_lookup_acc Φ l i x :
    l !! i = Some x 
    ([ list] ky  l, Φ k y)  Φ i x  (Φ i x - ([ list] ky  l, Φ k y)).
  Proof. intros. by rewrite {1}big_sepL_insert_acc // (forall_elim x) list_insert_id. Qed.

189
  Lemma big_sepL_lookup {Φ l} i x
190
    `{!TCOr ( j y, Affine (Φ j y)) (Absorbing (Φ i x))} :
191
    l !! i = Some x  ([ list] ky  l, Φ k y)  Φ i x.
192
193
194
195
196
197
198
  Proof.
    intros Hi. destruct select (TCOr _ _).
    - rewrite -(take_drop_middle l i x) // big_sepL_app /= take_length.
      apply lookup_lt_Some in Hi. rewrite (_ : _ + 0 = i); last lia.
      rewrite sep_elim_r sep_elim_l //.
    - rewrite big_sepL_lookup_acc // sep_elim_l //.
  Qed.
199

200
  Lemma big_sepL_elem_of {Φ : A  PROP} {l} x
201
    `{!TCOr ( y, Affine (Φ y)) (Absorbing (Φ x))} :
202
    x  l  ([ list] y  l, Φ y)  Φ x.
203
  Proof.
204
205
    intros [i ?]%elem_of_list_lookup.
    destruct select (TCOr _ _); by apply: big_sepL_lookup.
206
  Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
207

Robbert Krebbers's avatar
Robbert Krebbers committed
208
  Lemma big_sepL_fmap {B} (f : A  B) (Φ : nat  B  PROP) l :
209
    ([ list] ky  f <$> l, Φ k y)  ([ list] ky  l, Φ k (f y)).
210
  Proof. by rewrite big_opL_fmap. Qed.
211

212
213
214
215
  Lemma big_sepL_omap {B} (f : A  option B) (Φ : B  PROP) l :
    ([ list] y  omap f l, Φ y)  ([ list] y  l, from_option Φ emp (f y)).
  Proof. by rewrite big_opL_omap. Qed.

216
217
218
219
  Lemma big_sepL_bind {B} (f : A  list B) (Φ : B  PROP) l :
    ([ list] y  l = f, Φ y)  ([ list] x  l, [ list] y  f x, Φ y).
  Proof. by rewrite big_opL_bind. Qed.

220
  Lemma big_sepL_sep Φ Ψ l :
221
222
    ([ list] kx  l, Φ k x  Ψ k x)
     ([ list] kx  l, Φ k x)  ([ list] kx  l, Ψ k x).
223
  Proof. by rewrite big_opL_op. Qed.
224

225
226
227
228
229
230
  Lemma big_sepL_sep_2 Φ Ψ l :
    ([ list] kx  l, Φ k x) -
    ([ list] kx  l, Ψ k x) -
    ([ list] kx  l, Φ k x  Ψ k x).
  Proof. apply wand_intro_r. rewrite big_sepL_sep //. Qed.

231
232
233
  Lemma big_sepL_and Φ Ψ l :
    ([ list] kx  l, Φ k x  Ψ k x)
     ([ list] kx  l, Φ k x)  ([ list] kx  l, Ψ k x).
Robbert Krebbers's avatar
Robbert Krebbers committed
234
  Proof. auto using and_intro, big_sepL_mono, and_elim_l, and_elim_r. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
235

Ralf Jung's avatar
Ralf Jung committed
236
237
238
239
240
241
242
243
  Lemma big_sepL_pure_1 (φ : nat  A  Prop) l :
    ([ list] kx  l, ⌜φ k x) @{PROP}  k x, l !! k = Some x  φ k x.
  Proof.
    induction l as [|x l IH] using rev_ind.
    { apply pure_intro=>??. rewrite lookup_nil. done. }
    rewrite big_sepL_snoc // IH sep_and -pure_and.
    f_equiv=>-[Hl Hx] k y /lookup_app_Some =>-[Hy|[Hlen Hy]].
    - by apply Hl.
Ralf Jung's avatar
Ralf Jung committed
244
245
    - apply list_lookup_singleton_Some in Hy as [Hk ->].
      replace k with (length l) by lia. done.
Ralf Jung's avatar
Ralf Jung committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  Qed.
  Lemma big_sepL_affinely_pure_2 (φ : nat  A  Prop) l :
    <affine>  k x, l !! k = Some x  φ k x @{PROP} ([ list] kx  l, <affine> ⌜φ k x).
  Proof.
    induction l as [|x l IH] using rev_ind.
    { rewrite big_sepL_nil. apply affinely_elim_emp. }
    rewrite big_sepL_snoc // -IH.
    rewrite -persistent_and_sep_1 -affinely_and -pure_and.
    f_equiv. f_equiv=>- Hlx. split.
    - intros k y Hy. apply Hlx. rewrite lookup_app Hy //.
    - apply Hlx. rewrite lookup_app lookup_ge_None_2 //.
      rewrite Nat.sub_diag //.
  Qed.
  (** The general backwards direction requires [BiAffine] to cover the empty case. *)
  Lemma big_sepL_pure `{!BiAffine PROP} (φ : nat  A  Prop) l :
    ([ list] kx  l, ⌜φ k x) @{PROP}  k x, l !! k = Some x  φ k x.
  Proof.
    apply (anti_symm ()); first by apply big_sepL_pure_1.
264
    rewrite -(affine_affinely _).
Ralf Jung's avatar
Ralf Jung committed
265
266
267
    rewrite big_sepL_affinely_pure_2. by setoid_rewrite affinely_elim.
  Qed.

268
  Lemma big_sepL_persistently `{BiAffine PROP} Φ l :
269
    <pers> ([ list] kx  l, Φ k x)  [ list] kx  l, <pers> (Φ k x).
270
  Proof. apply (big_opL_commute _). Qed.
271

272
  Lemma big_sepL_intro Φ l :
273
274
275
276
277
278
279
280
281
282
     ( k x, l !! k = Some x  Φ k x)  [ list] kx  l, Φ k x.
  Proof.
    revert Φ. induction l as [|x l IH]=> Φ /=; [by apply (affine _)|].
    rewrite intuitionistically_sep_dup. f_equiv.
    - rewrite (forall_elim 0) (forall_elim x) pure_True // True_impl.
      by rewrite intuitionistically_elim.
    - rewrite -IH. f_equiv.
      apply forall_intro=> k; by rewrite (forall_elim (S k)).
  Qed.

283
  Lemma big_sepL_forall `{BiAffine PROP} Φ l :
284
    ( k x, Persistent (Φ k x)) 
Ralf Jung's avatar
Ralf Jung committed
285
    ([ list] kx  l, Φ k x)  ( k x, l !! k = Some x  Φ k x).
286
287
288
  Proof.
    intros HΦ. apply (anti_symm _).
    { apply forall_intro=> k; apply forall_intro=> x.
Robbert Krebbers's avatar
Robbert Krebbers committed
289
      apply impl_intro_l, pure_elim_l=> ?; by apply: big_sepL_lookup. }
290
291
292
293
294
    revert Φ HΦ. induction l as [|x l IH]=> Φ HΦ /=.
    { apply: affine. }
    rewrite -persistent_and_sep_1. apply and_intro.
    - rewrite (forall_elim 0) (forall_elim x) pure_True // True_impl. done.
    - rewrite -IH. apply forall_intro => k. by rewrite (forall_elim (S k)).
295
296
297
  Qed.

  Lemma big_sepL_impl Φ Ψ l :
Robbert Krebbers's avatar
Robbert Krebbers committed
298
    ([ list] kx  l, Φ k x) -
299
     ( k x, l !! k = Some x  Φ k x - Ψ k x) -
Robbert Krebbers's avatar
Robbert Krebbers committed
300
    [ list] kx  l, Ψ k x.
301
  Proof.
302
    apply wand_intro_l. rewrite big_sepL_intro -big_sepL_sep.
303
    by setoid_rewrite wand_elim_l.
304
305
  Qed.

Ralf Jung's avatar
Ralf Jung committed
306
307
308
309
310
311
312
313
314
  Lemma big_sepL_wand Φ Ψ l :
    ([ list] kx  l, Φ k x) -
    ([ list] kx  l, Φ k x - Ψ k x) -
    [ list] kx  l, Ψ k x.
  Proof.
    apply wand_intro_r. rewrite -big_sepL_sep.
    setoid_rewrite wand_elim_r. done.
  Qed.

315
  Lemma big_sepL_dup P `{!Affine P} l :
316
317
     (P - P  P) - P - [ list] kx  l, P.
  Proof.
318
319
    apply wand_intro_l.
    induction l as [|x l IH]=> /=; first by apply: affine.
320
321
322
323
    rewrite intuitionistically_sep_dup {1}intuitionistically_elim.
    rewrite assoc wand_elim_r -assoc. apply sep_mono; done.
  Qed.

324
325
  Lemma big_sepL_delete Φ l i x :
    l !! i = Some x 
326
327
    ([ list] ky  l, Φ k y) 
    Φ i x  [ list] ky  l, if decide (k = i) then emp else Φ k y.
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  Proof.
    intros. rewrite -(take_drop_middle l i x) // !big_sepL_app /= Nat.add_0_r.
    rewrite take_length_le; last eauto using lookup_lt_Some, Nat.lt_le_incl.
    rewrite decide_True // left_id.
    rewrite assoc -!(comm _ (Φ _ _)) -assoc. do 2 f_equiv.
    - apply big_sepL_proper=> k y Hk. apply lookup_lt_Some in Hk.
      rewrite take_length in Hk. by rewrite decide_False; last lia.
    - apply big_sepL_proper=> k y _. by rewrite decide_False; last lia.
  Qed.
  Lemma big_sepL_delete' `{!BiAffine PROP} Φ l i x :
    l !! i = Some x 
    ([ list] ky  l, Φ k y)  Φ i x  [ list] ky  l,  k  i   Φ k y.
  Proof.
    intros. rewrite big_sepL_delete //. (do 2 f_equiv)=> k y.
    rewrite -decide_emp. by repeat case_decide.
  Qed.

345
  Lemma big_sepL_lookup_acc_impl {Φ l} i x :
346
347
    l !! i = Some x 
    ([ list] ky  l, Φ k y) -
348
349
350
351
    (* We obtain [Φ] for [x] *)
    Φ i x 
    (* We reobtain the bigop for a predicate [Ψ] selected by the user *)
     Ψ,
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
       ( k y,  l !! k = Some y    k  i   Φ k y - Ψ k y) -
      Ψ i x -
      [ list] ky  l, Ψ k y.
  Proof.
    intros. rewrite big_sepL_delete //. apply sep_mono_r, forall_intro=> Ψ.
    apply wand_intro_r, wand_intro_l.
    rewrite (big_sepL_delete Ψ l i x) //. apply sep_mono_r.
    eapply wand_apply; [apply big_sepL_impl|apply sep_mono_r].
    apply intuitionistically_intro', forall_intro=> k; apply forall_intro=> y.
    apply impl_intro_l, pure_elim_l=> ?; apply wand_intro_r.
    rewrite (forall_elim ) (forall_elim y) pure_True // left_id.
    destruct (decide _) as [->|]; [by apply: affine|].
    by rewrite pure_True //left_id intuitionistically_elim wand_elim_l.
  Qed.

367
368
369
370
  Lemma big_sepL_replicate l P :
    [] replicate (length l) P  [ list] y  l, P.
  Proof. induction l as [|x l]=> //=; by f_equiv. Qed.

371
372
373
374
375
376
377
378
379
380
381
382
383
  Lemma big_sepL_later `{BiAffine PROP} Φ l :
     ([ list] kx  l, Φ k x)  ([ list] kx  l,  Φ k x).
  Proof. apply (big_opL_commute _). Qed.
  Lemma big_sepL_later_2 Φ l :
    ([ list] kx  l,  Φ k x)   [ list] kx  l, Φ k x.
  Proof. by rewrite (big_opL_commute _). Qed.

  Lemma big_sepL_laterN `{BiAffine PROP} Φ n l :
    ^n ([ list] kx  l, Φ k x)  ([ list] kx  l, ^n Φ k x).
  Proof. apply (big_opL_commute _). Qed.
  Lemma big_sepL_laterN_2 Φ n l :
    ([ list] kx  l, ^n Φ k x)  ^n [ list] kx  l, Φ k x.
  Proof. by rewrite (big_opL_commute _). Qed.
384
End sep_list.
385

Ralf Jung's avatar
Ralf Jung committed
386
(* Some lemmas depend on the generalized versions of the above ones. *)
387
388
389
390
391
392
393
394
Lemma big_sepL_sep_zip_with {A B C} (f : A  B  C) (g1 : C  A) (g2 : C  B)
    (Φ1 : nat  A  PROP) (Φ2 : nat  B  PROP) l1 l2 :
  ( x y, g1 (f x y) = x) 
  ( x y, g2 (f x y) = y) 
  length l1 = length l2 
  ([ list] kxy  zip_with f l1 l2, Φ1 k (g1 xy)  Φ2 k (g2 xy)) 
  ([ list] kx  l1, Φ1 k x)  ([ list] ky  l2, Φ2 k y).
Proof. apply big_opL_sep_zip_with. Qed.
395

396
Lemma big_sepL_sep_zip {A B} (Φ1 : nat  A  PROP) (Φ2 : nat  B  PROP) l1 l2 :
Ralf Jung's avatar
Ralf Jung committed
397
  length l1 = length l2 
398
399
400
  ([ list] kxy  zip l1 l2, Φ1 k xy.1  Φ2 k xy.2) 
  ([ list] kx  l1, Φ1 k x)  ([ list] ky  l2, Φ2 k y).
Proof. apply big_opL_sep_zip. Qed.
Ralf Jung's avatar
Ralf Jung committed
401
402

Lemma big_sepL_zip_with {A B C} (Φ : nat  A  PROP) f (l1 : list B) (l2 : list C) :
403
404
  ([ list] kx  zip_with f l1 l2, Φ k x) 
  ([ list] kx  l1, if l2 !! k is Some y then Φ k (f x y) else emp).
Ralf Jung's avatar
Ralf Jung committed
405
406
407
408
409
Proof.
  revert Φ l2; induction l1 as [|x l1 IH]=> Φ [|y l2] //=.
  - by rewrite big_sepL_emp left_id.
  - by rewrite IH.
Qed.
410

411
(** ** Big ops over two lists *)
412
Lemma big_sepL2_alt {A B} (Φ : nat  A  B  PROP) l1 l2 :
413
414
  ([ list] ky1;y2  l1; l2, Φ k y1 y2) 
   length l1 = length l2   [ list] k  xy  zip l1 l2, Φ k (xy.1) (xy.2).
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
Proof.
  apply (anti_symm _).
  - apply and_intro.
    + revert Φ l2. induction l1 as [|x1 l1 IH]=> Φ -[|x2 l2] /=;
        auto using pure_intro, False_elim.
      rewrite IH sep_elim_r. apply pure_mono; auto.
    + revert Φ l2. induction l1 as [|x1 l1 IH]=> Φ -[|x2 l2] /=;
        auto using pure_intro, False_elim.
      by rewrite IH.
  - apply pure_elim_l=> /Forall2_same_length Hl. revert Φ.
    induction Hl as [|x1 l1 x2 l2 _ _ IH]=> Φ //=. by rewrite -IH.
Qed.

Section sep_list2.
  Context {A B : Type}.
  Implicit Types Φ Ψ : nat  A  B  PROP.

  Lemma big_sepL2_nil Φ : ([ list] ky1;y2  []; [], Φ k y1 y2)  emp.
  Proof. done. Qed.
434
435
  Lemma big_sepL2_nil' P `{!Affine P} Φ : P  [ list] ky1;y2  [];[], Φ k y1 y2.
  Proof. apply: affine. Qed.
Dan Frumin's avatar
Dan Frumin committed
436
437
438
439
440
441
  Lemma big_sepL2_nil_inv_l Φ l2 :
    ([ list] ky1;y2  []; l2, Φ k y1 y2) - l2 = [].
  Proof. destruct l2; simpl; auto using False_elim, pure_intro. Qed.
  Lemma big_sepL2_nil_inv_r Φ l1 :
    ([ list] ky1;y2  l1; [], Φ k y1 y2) - l1 = [].
  Proof. destruct l1; simpl; auto using False_elim, pure_intro. Qed.
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

  Lemma big_sepL2_cons Φ x1 x2 l1 l2 :
    ([ list] ky1;y2  x1 :: l1; x2 :: l2, Φ k y1 y2)
     Φ 0 x1 x2  [ list] ky1;y2  l1;l2, Φ (S k) y1 y2.
  Proof. done. Qed.
  Lemma big_sepL2_cons_inv_l Φ x1 l1 l2 :
    ([ list] ky1;y2  x1 :: l1; l2, Φ k y1 y2) -
     x2 l2',  l2 = x2 :: l2'  
              Φ 0 x1 x2  [ list] ky1;y2  l1;l2', Φ (S k) y1 y2.
  Proof.
    destruct l2 as [|x2 l2]; simpl; auto using False_elim.
    by rewrite -(exist_intro x2) -(exist_intro l2) pure_True // left_id.
  Qed.
  Lemma big_sepL2_cons_inv_r Φ x2 l1 l2 :
    ([ list] ky1;y2  l1; x2 :: l2, Φ k y1 y2) -
     x1 l1',  l1 = x1 :: l1'  
              Φ 0 x1 x2  [ list] ky1;y2  l1';l2, Φ (S k) y1 y2.
  Proof.
    destruct l1 as [|x1 l1]; simpl; auto using False_elim.
    by rewrite -(exist_intro x1) -(exist_intro l1) pure_True // left_id.
  Qed.

  Lemma big_sepL2_singleton Φ x1 x2 :
    ([ list] ky1;y2  [x1];[x2], Φ k y1 y2)  Φ 0 x1 x2.
  Proof. by rewrite /= right_id. Qed.

  Lemma big_sepL2_length Φ l1 l2 :
    ([ list] ky1;y2  l1; l2, Φ k y1 y2) -  length l1 = length l2 .
  Proof. by rewrite big_sepL2_alt and_elim_l. Qed.

  Lemma big_sepL2_app Φ l1 l2 l1' l2' :
    ([ list] ky1;y2  l1; l1', Φ k y1 y2) -
    ([ list] ky1;y2  l2; l2', Φ (length l1 + k) y1 y2) -
    ([ list] ky1;y2  l1 ++ l2; l1' ++ l2', Φ k y1 y2).
  Proof.
    apply wand_intro_r. revert Φ l1'. induction l1 as [|x1 l1 IH]=> Φ -[|x1' l1'] /=.
    - by rewrite left_id.
    - rewrite left_absorb. apply False_elim.
    - rewrite left_absorb. apply False_elim.
    - by rewrite -assoc IH.
  Qed.
  Lemma big_sepL2_app_inv_l Φ l1' l1'' l2 :
    ([ list] ky1;y2  l1' ++ l1''; l2, Φ k y1 y2) -
     l2' l2'',  l2 = l2' ++ l2''  
                ([ list] ky1;y2  l1';l2', Φ k y1 y2) 
                ([ list] ky1;y2  l1'';l2'', Φ (length l1' + k) y1 y2).
  Proof.
    rewrite -(exist_intro (take (length l1') l2))
      -(exist_intro (drop (length l1') l2)) take_drop pure_True // left_id.
    revert Φ l2. induction l1' as [|x1 l1' IH]=> Φ -[|x2 l2] /=;
       [by rewrite left_id|by rewrite left_id|apply False_elim|].
    by rewrite IH -assoc.
  Qed.
  Lemma big_sepL2_app_inv_r Φ l1 l2' l2'' :
    ([ list] ky1;y2  l1; l2' ++ l2'', Φ k y1 y2) -
     l1' l1'',  l1 = l1' ++ l1''  
                ([ list] ky1;y2  l1';l2', Φ k y1 y2) 
                ([ list] ky1;y2  l1'';l2'', Φ (length l2' + k) y1 y2).
  Proof.
    rewrite -(exist_intro (take (length l2') l1))
      -(exist_intro (drop (length l2') l1)) take_drop pure_True // left_id.
    revert Φ l1. induction l2' as [|x2 l2' IH]=> Φ -[|x1 l1] /=;
       [by rewrite left_id|by rewrite left_id|apply False_elim|].
    by rewrite IH -assoc.
  Qed.
507
  Lemma big_sepL2_app_inv Φ l1 l2 l1' l2' :
508
    length l1 = length l1'  length l2 = length l2' 
509
510
511
512
    ([ list] ky1;y2  l1 ++ l2; l1' ++ l2', Φ k y1 y2) -
    ([ list] ky1;y2  l1; l1', Φ k y1 y2) 
    ([ list] ky1;y2  l2; l2', Φ (length l1 + k)%nat y1 y2).
  Proof.
513
    revert Φ l1'. induction l1 as [|x1 l1 IH]=> Φ -[|x1' l1'] /= Hlen.
514
    - by rewrite left_id.
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
    - destruct Hlen as [[=]|Hlen]. rewrite big_sepL2_length Hlen /= app_length.
      apply pure_elim'; lia.
    - destruct Hlen as [[=]|Hlen]. rewrite big_sepL2_length -Hlen /= app_length.
      apply pure_elim'; lia.
    - by rewrite -assoc IH; last lia.
  Qed.
  Lemma big_sepL2_app_same_length Φ l1 l2 l1' l2' :
    length l1 = length l1'  length l2 = length l2' 
    ([ list] ky1;y2  l1 ++ l2; l1' ++ l2', Φ k y1 y2) 
    ([ list] ky1;y2  l1; l1', Φ k y1 y2) 
    ([ list] ky1;y2  l2; l2', Φ (length l1 + k)%nat y1 y2).
  Proof.
    intros. apply (anti_symm _).
    - by apply big_sepL2_app_inv.
    - apply wand_elim_l'. apply big_sepL2_app.
530
  Qed.
531

Ralf Jung's avatar
Ralf Jung committed
532
  Lemma big_sepL2_snoc Φ x1 x2 l1 l2 :
533
534
    ([ list] ky1;y2  l1 ++ [x1]; l2 ++ [x2], Φ k y1 y2) 
    ([ list] ky1;y2  l1; l2, Φ k y1 y2)  Φ (length l1) x1 x2.
Ralf Jung's avatar
Ralf Jung committed
535
  Proof.
536
537
    rewrite big_sepL2_app_same_length; last by auto.
    by rewrite big_sepL2_singleton Nat.add_0_r.
Ralf Jung's avatar
Ralf Jung committed
538
539
  Qed.

540
541
  (** The lemmas [big_sepL2_mono], [big_sepL2_ne] and [big_sepL2_proper] are more
  generic than the instances as they also give [li !! k = Some yi] in the premise. *)
542
543
544
545
546
547
548
  Lemma big_sepL2_mono Φ Ψ l1 l2 :
    ( k y1 y2, l1 !! k = Some y1  l2 !! k = Some y2  Φ k y1 y2  Ψ k y1 y2) 
    ([ list] k  y1;y2  l1;l2, Φ k y1 y2)  [ list] k  y1;y2  l1;l2, Ψ k y1 y2.
  Proof.
    intros H. rewrite !big_sepL2_alt. f_equiv. apply big_sepL_mono=> k [y1 y2].
    rewrite lookup_zip_with=> ?; simplify_option_eq; auto.
  Qed.
549
550
551
552
553
554
555
  Lemma big_sepL2_ne Φ Ψ l1 l2 n :
    ( k y1 y2, l1 !! k = Some y1  l2 !! k = Some y2  Φ k y1 y2 {n} Ψ k y1 y2) 
    ([ list] k  y1;y2  l1;l2, Φ k y1 y2)%I {n} ([ list] k  y1;y2  l1;l2, Ψ k y1 y2)%I.
  Proof.
    intros H. rewrite !big_sepL2_alt. f_equiv. apply big_sepL_ne=> k [y1 y2].
    rewrite lookup_zip_with=> ?; simplify_option_eq; auto.
  Qed.
556
557
558
559
560
  Lemma big_sepL2_proper Φ Ψ l1 l2 :
    ( k y1 y2, l1 !! k = Some y1  l2 !! k = Some y2  Φ k y1 y2  Ψ k y1 y2) 
    ([ list] k  y1;y2  l1;l2, Φ k y1 y2)  [ list] k  y1;y2  l1;l2, Ψ k y1 y2.
  Proof.
    intros; apply (anti_symm _);
561
      apply big_sepL2_mono; auto using equiv_entails_1_1, equiv_entails_1_2.
562
  Qed.
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  Lemma big_sepL2_proper_2 `{!Equiv A, !Equiv B} Φ Ψ l1 l2 l1' l2' :
    l1  l1'  l2  l2' 
    ( k y1 y1' y2 y2',
      l1 !! k = Some y1  l1' !! k = Some y1'  y1  y1' 
      l2 !! k = Some y2  l2' !! k = Some y2'  y2  y2' 
      Φ k y1 y2  Ψ k y1' y2') 
    ([ list] k  y1;y2  l1;l2, Φ k y1 y2)  [ list] k  y1;y2  l1';l2', Ψ k y1 y2.
  Proof.
    intros Hl1 Hl2 Hf. rewrite !big_sepL2_alt. f_equiv.
    { do 2 f_equiv; by apply length_proper. }
    apply big_opL_proper_2; [by f_equiv|].
    intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%lookup_zip_with_Some
      (?&?&[=<- <-]&?&?)%lookup_zip_with_Some [??]; naive_solver.
  Qed.
577

578
  Global Instance big_sepL2_ne' n :
579
580
581
    Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (dist n)))
      ==> (=) ==> (=) ==> (dist n))
           (big_sepL2 (PROP:=PROP) (A:=A) (B:=B)).
582
  Proof. intros f g Hf l1 ? <- l2 ? <-. apply big_sepL2_ne; intros; apply Hf. Qed.
583
584
585
586
587
588
589
590
591
592
593
  Global Instance big_sepL2_mono' :
    Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ ()))
      ==> (=) ==> (=) ==> ())
           (big_sepL2 (PROP:=PROP) (A:=A) (B:=B)).
  Proof. intros f g Hf l1 ? <- l2 ? <-. apply big_sepL2_mono; intros; apply Hf. Qed.
  Global Instance big_sepL2_proper' :
    Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ ()))
      ==> (=) ==> (=) ==> ())
           (big_sepL2 (PROP:=PROP) (A:=A) (B:=B)).
  Proof. intros f g Hf l1 ? <- l2 ? <-. apply big_sepL2_proper; intros; apply Hf. Qed.

Robbert Krebbers's avatar
Robbert Krebbers committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
  Global Instance big_sepL2_nil_persistent Φ :
    Persistent ([ list] ky1;y2  []; [], Φ k y1 y2).
  Proof. simpl; apply _. Qed.
  Global Instance big_sepL2_persistent Φ l1 l2 :
    ( k x1 x2, Persistent (Φ k x1 x2)) 
    Persistent ([ list] ky1;y2  l1;l2, Φ k y1 y2).
  Proof. rewrite big_sepL2_alt. apply _. Qed.

  Global Instance big_sepL2_nil_affine Φ :
    Affine ([ list] ky1;y2  []; [], Φ k y1 y2).
  Proof. simpl; apply _. Qed.
  Global Instance big_sepL2_affine Φ l1 l2 :
    ( k x1 x2, Affine (Φ k x1 x2)) 
    Affine ([ list] ky1;y2  l1;l2, Φ k y1 y2).
  Proof. rewrite big_sepL2_alt. apply _. Qed.

  Global Instance big_sepL2_nil_timeless `{!Timeless (emp%I : PROP)} Φ :
    Timeless ([ list] ky1;y2  []; [], Φ k y1 y2).
  Proof. simpl; apply _. Qed.
  Global Instance big_sepL2_timeless `{!Timeless (emp%I : PROP)} Φ l1 l2 :
    ( k x1 x2, Timeless (Φ k x1 x2)) 
    Timeless ([ list] ky1;y2  l1;l2, Φ k y1 y2).
  Proof. rewrite big_sepL2_alt. apply _. Qed.

618
619
620
621
622
623
624
625
626
627
628
629
  Lemma big_sepL2_insert_acc Φ l1 l2 i x1 x2 :
    l1 !! i = Some x1  l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) 
    Φ i x1 x2  ( y1 y2, Φ i y1 y2 - ([ list] ky1;y2  <[i:=y1]>l1;<[i:=y2]>l2, Φ k y1 y2)).
  Proof.
    intros Hl1 Hl2. rewrite big_sepL2_alt. apply pure_elim_l=> Hl.
    rewrite {1}big_sepL_insert_acc; last by rewrite lookup_zip_with; simplify_option_eq.
    apply sep_mono_r. apply forall_intro => y1. apply forall_intro => y2.
    rewrite big_sepL2_alt !insert_length pure_True // left_id -insert_zip_with.
    by rewrite (forall_elim (y1, y2)).
  Qed.

630
631
632
633
634
  Lemma big_sepL2_lookup_acc Φ l1 l2 i x1 x2 :
    l1 !! i = Some x1  l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) 
    Φ i x1 x2  (Φ i x1 x2 - ([ list] ky1;y2  l1;l2, Φ k y1 y2)).
  Proof.
635
636
    intros. rewrite {1}big_sepL2_insert_acc // (forall_elim x1) (forall_elim x2).
    by rewrite !list_insert_id.
637
638
  Qed.

639
  Lemma big_sepL2_lookup {Φ l1 l2} i x1 x2
640
    `{!TCOr ( j y1 y2, Affine (Φ j y1 y2)) (Absorbing (Φ i x1 x2))} :
641
642
    l1 !! i = Some x1  l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2)  Φ i x1 x2.
643
644
645
646
647
648
649
650
651
  Proof.
    intros Hx1 Hx2. destruct select (TCOr _ _).
    - rewrite -(take_drop_middle l1 i x1) // -(take_drop_middle l2 i x2) //.
      apply lookup_lt_Some in Hx1. apply lookup_lt_Some in Hx2.
      rewrite big_sepL2_app_same_length /= 2?take_length; last lia.
      rewrite (_ : _ + 0 = i); last lia.
      rewrite sep_elim_r sep_elim_l //.
    - rewrite big_sepL2_lookup_acc // sep_elim_l //.
  Qed.
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667

  Lemma big_sepL2_fmap_l {A'} (f : A  A') (Φ : nat  A'  B  PROP) l1 l2 :
    ([ list] ky1;y2  f <$> l1; l2, Φ k y1 y2)
     ([ list] ky1;y2  l1;l2, Φ k (f y1) y2).
  Proof.
    rewrite !big_sepL2_alt fmap_length zip_with_fmap_l zip_with_zip big_sepL_fmap.
    by f_equiv; f_equiv=> k [??].
  Qed.
  Lemma big_sepL2_fmap_r {B'} (g : B  B') (Φ : nat  A  B'  PROP) l1 l2 :
    ([ list] ky1;y2  l1; g <$> l2, Φ k y1 y2)
     ([ list] ky1;y2  l1;l2, Φ k y1 (g y2)).
  Proof.
    rewrite !big_sepL2_alt fmap_length zip_with_fmap_r zip_with_zip big_sepL_fmap.
    by f_equiv; f_equiv=> k [??].
  Qed.

668
669
670
671
672
673
674
675
676
677
678
  Lemma big_sepL2_reverse_2 (Φ : A  B  PROP) l1 l2 :
    ([ list] y1;y2  l1;l2, Φ y1 y2)  ([ list] y1;y2  reverse l1;reverse l2, Φ y1 y2).
  Proof.
    revert l2. induction l1 as [|x1 l1 IH]; intros [|x2 l2]; simpl; auto using False_elim.
    rewrite !reverse_cons (comm bi_sep) IH.
    by rewrite (big_sepL2_app _ _ [x1] _ [x2]) big_sepL2_singleton wand_elim_l.
  Qed.
  Lemma big_sepL2_reverse (Φ : A  B  PROP) l1 l2 :
    ([ list] y1;y2  reverse l1;reverse l2, Φ y1 y2)  ([ list] y1;y2  l1;l2, Φ y1 y2).
  Proof. apply (anti_symm _); by rewrite big_sepL2_reverse_2 ?reverse_involutive. Qed.

679
680
681
682
683
684
685
686
687
  Lemma big_sepL2_replicate_l l x Φ n :
    length l = n 
    ([ list] kx1;x2  replicate n x; l, Φ k x1 x2)  [ list] kx2  l, Φ k x x2.
  Proof. intros <-. revert Φ. induction l as [|y l IH]=> //= Φ. by rewrite IH. Qed.
  Lemma big_sepL2_replicate_r l x Φ n :
    length l = n 
    ([ list] kx1;x2  l;replicate n x, Φ k x1 x2)  [ list] kx1  l, Φ k x1 x.
  Proof. intros <-. revert Φ. induction l as [|y l IH]=> //= Φ. by rewrite IH. Qed.

688
  Lemma big_sepL2_sep Φ Ψ l1 l2 :
689
690
691
    ([ list] ky1;y2  l1;l2, Φ k y1 y2  Ψ k y1 y2)
     ([ list] ky1;y2  l1;l2, Φ k y1 y2)  ([ list] ky1;y2  l1;l2, Ψ k y1 y2).
  Proof.
692
    rewrite !big_sepL2_alt big_sepL_sep !persistent_and_affinely_sep_l.
693
694
695
696
697
    rewrite -assoc (assoc _ _ (<affine> _)%I). rewrite -(comm bi_sep (<affine> _)%I).
    rewrite -assoc (assoc _ _ (<affine> _)%I) -!persistent_and_affinely_sep_l.
    by rewrite affinely_and_r persistent_and_affinely_sep_l idemp.
  Qed.

698
699
700
701
702
703
  Lemma big_sepL2_sep_2 Φ Ψ l1 l2 :
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) -
    ([ list] ky1;y2  l1;l2, Ψ k y1 y2) -
    ([ list] ky1;y2  l1;l2, Φ k y1 y2  Ψ k y1 y2).
  Proof. apply wand_intro_r. rewrite big_sepL2_sep //. Qed.

704
705
706
707
708
  Lemma big_sepL2_and Φ Ψ l1 l2 :
    ([ list] ky1;y2  l1;l2, Φ k y1 y2  Ψ k y1 y2)
     ([ list] ky1;y2  l1;l2, Φ k y1 y2)  ([ list] ky1;y2  l1;l2, Ψ k y1 y2).
  Proof. auto using and_intro, big_sepL2_mono, and_elim_l, and_elim_r. Qed.

Ralf Jung's avatar
Ralf Jung committed
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  Lemma big_sepL2_pure_1 (φ : nat  A  B  Prop) l1 l2 :
    ([ list] ky1;y2  l1;l2, ⌜φ k y1 y2) @{PROP}
       k y1 y2, l1 !! k = Some y1  l2 !! k = Some y2  φ k y1 y2.
  Proof.
    rewrite big_sepL2_alt big_sepL_pure_1.
    rewrite -pure_and. f_equiv=>-[Hlen Hlookup] k y1 y2 Hy1 Hy2.
    eapply (Hlookup k (y1, y2)).
    rewrite lookup_zip_with Hy1 /= Hy2 /= //.
  Qed.
  Lemma big_sepL2_affinely_pure_2 (φ : nat  A  B  Prop) l1 l2 :
    length l1 = length l2 
    <affine>  k y1 y2, l1 !! k = Some y1  l2 !! k = Some y2  φ k y1 y2 @{PROP}
    ([ list] ky1;y2  l1;l2, <affine> ⌜φ k y1 y2).
  Proof.
    intros Hdom. rewrite big_sepL2_alt.
    rewrite -big_sepL_affinely_pure_2.
    rewrite affinely_and_r -pure_and. f_equiv. f_equiv=>-Hforall.
    split; first done.
    intros k [y1 y2] (? & ? & [= <- <-] & Hy1 & Hy2)%lookup_zip_with_Some.
    by eapply Hforall.
  Qed.
  (** The general backwards direction requires [BiAffine] to cover the empty case. *)
  Lemma big_sepL2_pure `{!BiAffine PROP} (φ : nat  A  B  Prop) l1 l2 :
    ([ list] ky1;y2  l1;l2, ⌜φ k y1 y2) @{PROP}
      length l1 = length l2 
        k y1 y2, l1 !! k = Some y1  l2 !! k = Some y2  φ k y1 y2.
  Proof.
    apply (anti_symm ()).
    { rewrite pure_and. apply and_intro.
      - apply big_sepL2_length.
      - apply big_sepL2_pure_1. }
    rewrite -(affine_affinely _%I).
    rewrite pure_and -affinely_and_r.
    apply pure_elim_l=>Hdom.
    rewrite big_sepL2_affinely_pure_2 //. by setoid_rewrite affinely_elim.
  Qed.

746
747
748
749
750
751
752
  Lemma big_sepL2_persistently `{BiAffine PROP} Φ l1 l2 :
    <pers> ([ list] ky1;y2  l1;l2, Φ k y1 y2)
     [ list] ky1;y2  l1;l2, <pers> (Φ k y1 y2).
  Proof.
    by rewrite !big_sepL2_alt persistently_and persistently_pure big_sepL_persistently.
  Qed.

753
  Lemma big_sepL2_intro Φ l1 l2 :
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
    length l1 = length l2 
     ( k x1 x2, l1 !! k = Some x1  l2 !! k = Some x2  Φ k x1 x2) 
    [ list] kx1;x2  l1;l2, Φ k x1 x2.
  Proof.
    revert l2 Φ. induction l1 as [|x1 l1 IH]=> -[|x2 l2] Φ ?; simplify_eq/=.
    { by apply (affine _). }
    rewrite intuitionistically_sep_dup. f_equiv.
    - rewrite (forall_elim 0) (forall_elim x1) (forall_elim x2).
      by rewrite !pure_True // !True_impl intuitionistically_elim.
    - rewrite -IH //. f_equiv.
      by apply forall_intro=> k; by rewrite (forall_elim (S k)).
  Qed.

  Lemma big_sepL2_forall `{BiAffine PROP} Φ l1 l2 :
    ( k x1 x2, Persistent (Φ k x1 x2)) 
    ([ list] kx1;x2  l1;l2, Φ k x1 x2) 
      length l1 = length l2
       ( k x1 x2, l1 !! k = Some x1  l2 !! k = Some x2  Φ k x1 x2).
  Proof.
773
774
    intros HΦ. apply (anti_symm _).
    { apply and_intro; [apply big_sepL2_length|].
775
      apply forall_intro=> k. apply forall_intro=> x1. apply forall_intro=> x2.
Paolo G. Giarrusso's avatar
Paolo G. Giarrusso committed
776
      do 2 (apply impl_intro_l; apply pure_elim_l=> ?). by apply: big_sepL2_lookup. }
777
778
779
780
781
782
783
784
    apply pure_elim_l=> Hlen.
    revert l2 Φ HΦ Hlen. induction l1 as [|x1 l1 IH]=> -[|x2 l2] Φ HΦ Hlen; simplify_eq/=.
    { by apply (affine _). }
    rewrite -persistent_and_sep_1. apply and_intro.
    - rewrite (forall_elim 0) (forall_elim x1) (forall_elim x2).
      by rewrite !pure_True // !True_impl.
    - rewrite -IH //.
      by apply forall_intro=> k; by rewrite (forall_elim (S k)).
785
786
  Qed.

787
788
789
790
791
792
  Lemma big_sepL2_impl Φ Ψ l1 l2 :
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) -
     ( k x1 x2,
      l1 !! k = Some x1  l2 !! k = Some x2  Φ k x1 x2 - Ψ k x1 x2) -
    [ list] ky1;y2  l1;l2, Ψ k y1 y2.
  Proof.
793
    rewrite -(idemp bi_and (big_sepL2 _ _ _)) {1}big_sepL2_length.
794
    apply pure_elim_l=> ?. rewrite big_sepL2_intro //.
795
    apply bi.wand_intro_l. rewrite -big_sepL2_sep. by setoid_rewrite wand_elim_l.
796
797
  Qed.

Ralf Jung's avatar
Ralf Jung committed
798
799
800
801
802
803
804
805
806
  Lemma big_sepL2_wand Φ Ψ l1 l2 :
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) -
    ([ list] ky1;y2  l1;l2, Φ k y1 y2 - Ψ k y1 y2) -
    [ list] ky1;y2  l1;l2, Ψ k y1 y2.
  Proof.
    apply wand_intro_r. rewrite -big_sepL2_sep.
    setoid_rewrite wand_elim_r. done.
  Qed.

807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
  Lemma big_sepL2_delete Φ l1 l2 i x1 x2 :
    l1 !! i = Some x1  l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) 
    Φ i x1 x2  [ list] ky1;y2  l1;l2, if decide (k = i) then emp else Φ k y1 y2.
  Proof.
    intros. rewrite -(take_drop_middle l1 i x1) // -(take_drop_middle l2 i x2) //.
    assert (i < length l1  i < length l2) as [??] by eauto using lookup_lt_Some.
    rewrite !big_sepL2_app_same_length /=; [|rewrite ?take_length; lia..].
    rewrite Nat.add_0_r take_length_le; [|lia].
    rewrite decide_True // left_id.
    rewrite assoc -!(comm _ (Φ _ _ _)) -assoc. do 2 f_equiv.
    - apply big_sepL2_proper=> k y1 y2 Hk. apply lookup_lt_Some in Hk.
      rewrite take_length in Hk. by rewrite decide_False; last lia.
    - apply big_sepL2_proper=> k y1 y2 _. by rewrite decide_False; last lia.
  Qed.
  Lemma big_sepL2_delete' `{!BiAffine PROP} Φ l1 l2 i x1 x2 :
    l1 !! i = Some x1  l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) 
    Φ i x1 x2  [ list] ky1;y2  l1;l2,  k  i   Φ k y1 y2.
  Proof.
    intros. rewrite big_sepL2_delete //. (do 2 f_equiv)=> k y1 y2.
    rewrite -decide_emp. by repeat case_decide.
  Qed.

831
  Lemma big_sepL2_lookup_acc_impl {Φ l1 l2} i x1 x2 :
832
833
834
    l1 !! i = Some x1 
    l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) -
835
836
837
838
    (* We obtain [Φ] for the [x1] and [x2] *)
    Φ i x1 x2 
    (* We reobtain the bigop for a predicate [Ψ] selected by the user *)
     Ψ,
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
       ( k y1 y2,
         l1 !! k = Some y1    l2 !! k = Some y2    k  i  
        Φ k y1 y2 - Ψ k y1 y2) -
      Ψ i x1 x2 -
      [ list] ky1;y2  l1;l2, Ψ k y1 y2.
  Proof.
    intros. rewrite big_sepL2_delete //. apply sep_mono_r, forall_intro=> Ψ.
    apply wand_intro_r, wand_intro_l.
    rewrite (big_sepL2_delete Ψ l1 l2 i) //. apply sep_mono_r.
    eapply wand_apply; [apply big_sepL2_impl|apply sep_mono_r].
    apply intuitionistically_intro', forall_intro=> k;
      apply forall_intro=> y1; apply forall_intro=> y2.
    do 2 (apply impl_intro_l, pure_elim_l=> ?); apply wand_intro_r.
    rewrite (forall_elim k) (forall_elim y1) (forall_elim y2).
    rewrite !(pure_True (_ = Some _)) // !left_id.
    destruct (decide _) as [->|]; [by apply: affine|].
    by rewrite pure_True //left_id intuitionistically_elim wand_elim_l.
  Qed.

858
859
860
  Lemma big_sepL2_later_1 `{BiAffine PROP} Φ l1 l2 :
    ( [ list] ky1;y2  l1;l2, Φ k y1 y2)   [ list] ky1;y2  l1;l2,  Φ k y1 y2.
  Proof.