big_op.v 94.9 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
10
11
12
13
14
15
16
17
18
19
20
Notation "'[∗' 'list]' k ↦ x ∈ l , P" :=
  (big_opL bi_sep (λ k x, P) l) : bi_scope.
Notation "'[∗' 'list]' x ∈ l , P" :=
  (big_opL bi_sep (λ _ x, P) l) : bi_scope.
Notation "'[∗]' Ps" := (big_opL bi_sep (λ _ x, x) Ps) : bi_scope.

Notation "'[∧' 'list]' k ↦ x ∈ l , P" :=
  (big_opL bi_and (λ k x, P) l) : bi_scope.
Notation "'[∧' 'list]' x ∈ l , P" :=
  (big_opL bi_and (λ _ x, P) l) : bi_scope.
Notation "'[∧]' Ps" := (big_opL bi_and (λ _ x, x) Ps) : bi_scope.

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

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

Notation "'[∗' 'set]' x ∈ X , P" := (big_opS bi_sep (λ x, P) X) : bi_scope.

Notation "'[∗' 'mset]' x ∈ X , P" := (big_opMS bi_sep (λ x, P) X) : bi_scope.
33

Dan Frumin's avatar
Dan Frumin committed
34
35
36
37
38
39
40
41
42
43
44
45
(** 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.
46
Global Instance: Params (@big_sepL2) 3 := {}.
Ralf Jung's avatar
Ralf Jung committed
47
Global Arguments big_sepL2 {PROP A B} _ !_ !_ /.
Dan Frumin's avatar
Dan Frumin committed
48
49
50
51
52
53
Typeclasses Opaque big_sepL2.
Notation "'[∗' 'list]' k ↦ x1 ; x2 ∈ l1 ; l2 , P" :=
  (big_sepL2 (λ k x1 x2, P) l1 l2) : bi_scope.
Notation "'[∗' 'list]' x1 ; x2 ∈ l1 ; l2 , P" :=
  (big_sepL2 (λ _ x1 x2, P) l1 l2) : bi_scope.

54
Definition big_sepM2_def {PROP : bi} `{Countable K} {A B}
Dan Frumin's avatar
Dan Frumin committed
55
56
57
    (Φ : 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.
58
Definition big_sepM2_aux : seal (@big_sepM2_def). Proof. by eexists. Qed.
59
Definition big_sepM2 := big_sepM2_aux.(unseal).
Ralf Jung's avatar
Ralf Jung committed
60
Global Arguments big_sepM2 {PROP K _ _ A B} _ _ _.
Ralf Jung's avatar
Ralf Jung committed
61
Definition big_sepM2_eq : @big_sepM2 = _ := big_sepM2_aux.(seal_eq).
62
Global Instance: Params (@big_sepM2) 6 := {}.
Dan Frumin's avatar
Dan Frumin committed
63
64
65
66
67
Notation "'[∗' 'map]' k ↦ x1 ; x2 ∈ m1 ; m2 , P" :=
  (big_sepM2 (λ k x1 x2, P) m1 m2) : bi_scope.
Notation "'[∗' 'map]' x1 ; x2 ∈ m1 ; m2 , P" :=
  (big_sepM2 (λ _ x1 x2, P) m1 m2) : bi_scope.

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

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

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

98
99
100
101
102
103
104
105
  Lemma big_sepL_submseteq `{BiAffine PROP} (Φ : A  PROP) l1 l2 :
    l1 + l2  ([ list] y  l2, Φ y)  [ list] y  l1, Φ y.
  Proof.
    intros [l ->]%submseteq_Permutation. by rewrite big_sepL_app sep_elim_l.
  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. *)
106
107
  Lemma big_sepL_mono Φ Ψ l :
    ( k y, l !! k = Some y  Φ k y  Ψ k y) 
108
    ([ list] k  y  l, Φ k y)  [ list] k  y  l, Ψ k y.
109
  Proof. apply big_opL_gen_proper; apply _. Qed.
110
111
112
113
  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.
114
115
  Lemma big_sepL_proper Φ Ψ l :
    ( k y, l !! k = Some y  Φ k y  Ψ k y) 
116
    ([ list] k  y  l, Φ k y)  ([ list] k  y  l, Ψ k y).
117
  Proof. apply big_opL_proper. Qed.
118

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

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

132
  Lemma big_sepL_insert_acc Φ l i x :
133
    l !! i = Some x 
134
    ([ list] ky  l, Φ k y)  Φ i x  ( y, Φ i y - ([ list] ky  <[i:=y]>l, Φ k y)).
135
  Proof.
136
137
138
139
140
141
142
143
    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.
144
145
  Qed.

146
147
148
149
150
  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.

Robbert Krebbers's avatar
Robbert Krebbers committed
151
  Lemma big_sepL_lookup Φ l i x `{!Absorbing (Φ i x)} :
152
    l !! i = Some x  ([ list] ky  l, Φ k y)  Φ i x.
Robbert Krebbers's avatar
Robbert Krebbers committed
153
  Proof. intros. rewrite big_sepL_lookup_acc //. by rewrite sep_elim_l. Qed.
154

Robbert Krebbers's avatar
Robbert Krebbers committed
155
  Lemma big_sepL_elem_of (Φ : A  PROP) l x `{!Absorbing (Φ x)} :
156
    x  l  ([ list] y  l, Φ y)  Φ x.
157
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
158
    intros [i ?]%elem_of_list_lookup. by eapply (big_sepL_lookup (λ _, Φ)).
159
  Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
160

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

165
166
167
168
  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.

169
170
171
172
  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.

173
  Lemma big_sepL_sep Φ Ψ l :
174
175
    ([ list] kx  l, Φ k x  Ψ k x)
     ([ list] kx  l, Φ k x)  ([ list] kx  l, Ψ k x).
176
  Proof. by rewrite big_opL_op. Qed.
177

178
179
180
  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
181
  Proof. auto using and_intro, big_sepL_mono, and_elim_l, and_elim_r. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
182

183
  Lemma big_sepL_persistently `{BiAffine PROP} Φ l :
184
    <pers> ([ list] kx  l, Φ k x)  [ list] kx  l, <pers> (Φ k x).
185
  Proof. apply (big_opL_commute _). Qed.
186

187
188
189
190
191
192
193
194
195
196
197
  Lemma big_sepL_intuitionistically_forall Φ l :
     ( 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.

198
  Lemma big_sepL_forall `{BiAffine PROP} Φ l :
199
    ( k x, Persistent (Φ k x)) 
Ralf Jung's avatar
Ralf Jung committed
200
    ([ list] kx  l, Φ k x)  ( k x, l !! k = Some x  Φ k x).
201
202
203
  Proof.
    intros HΦ. apply (anti_symm _).
    { apply forall_intro=> k; apply forall_intro=> x.
Robbert Krebbers's avatar
Robbert Krebbers committed
204
      apply impl_intro_l, pure_elim_l=> ?; by apply: big_sepL_lookup. }
205
206
    rewrite -big_sepL_intuitionistically_forall. setoid_rewrite pure_impl_forall.
    by rewrite intuitionistic_intuitionistically.
207
208
209
  Qed.

  Lemma big_sepL_impl Φ Ψ l :
Robbert Krebbers's avatar
Robbert Krebbers committed
210
    ([ list] kx  l, Φ k x) -
211
     ( k x, l !! k = Some x  Φ k x - Ψ k x) -
Robbert Krebbers's avatar
Robbert Krebbers committed
212
    [ list] kx  l, Ψ k x.
213
  Proof.
214
215
    apply wand_intro_l. rewrite big_sepL_intuitionistically_forall -big_sepL_sep.
    by setoid_rewrite wand_elim_l.
216
217
  Qed.

218
  Lemma big_sepL_dup P `{!Affine P} l :
219
220
     (P - P  P) - P - [ list] kx  l, P.
  Proof.
221
222
    apply wand_intro_l.
    induction l as [|x l IH]=> /=; first by apply: affine.
223
224
225
226
    rewrite intuitionistically_sep_dup {1}intuitionistically_elim.
    rewrite assoc wand_elim_r -assoc. apply sep_mono; done.
  Qed.

227
228
  Lemma big_sepL_delete Φ l i x :
    l !! i = Some x 
229
230
    ([ list] ky  l, Φ k y) 
    Φ i x  [ list] ky  l, if decide (k = i) then emp else Φ k y.
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  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.

248
  Lemma big_sepL_lookup_acc_impl {Φ l} i x :
249
250
    l !! i = Some x 
    ([ list] ky  l, Φ k y) -
251
252
253
254
    (* We obtain [Φ] for [x] *)
    Φ i x 
    (* We reobtain the bigop for a predicate [Ψ] selected by the user *)
     Ψ,
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
       ( 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.

270
271
272
273
  Lemma big_sepL_replicate l P :
    [] replicate (length l) P  [ list] y  l, P.
  Proof. induction l as [|x l]=> //=; by f_equiv. Qed.

274
275
276
277
278
279
280
281
282
283
284
285
286
287
  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.

288
  Global Instance big_sepL_nil_persistent Φ :
289
    Persistent ([ list] kx  [], Φ k x).
290
  Proof. simpl; apply _. Qed.
291
  Global Instance big_sepL_persistent Φ l :
292
    ( k x, Persistent (Φ k x))  Persistent ([ list] kx  l, Φ k x).
293
  Proof. revert Φ. induction l as [|x l IH]=> Φ ? /=; apply _. Qed.
294
  Global Instance big_sepL_persistent_id Ps :
295
    TCForall Persistent Ps  Persistent ([] Ps).
296
  Proof. induction 1; simpl; apply _. Qed.
297

298
299
300
  Global Instance big_sepL_nil_affine Φ :
    Affine ([ list] kx  [], Φ k x).
  Proof. simpl; apply _. Qed.
301
302
303
  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.
304
305
  Global Instance big_sepL_affine_id Ps : TCForall Affine Ps  Affine ([] Ps).
  Proof. induction 1; simpl; apply _. Qed.
306
307
308
309
310
311
312
313
314
315

  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.
316
End sep_list.
317

Ralf Jung's avatar
Ralf Jung committed
318
(* Some lemmas depend on the generalized versions of the above ones. *)
319
320
321
322
323
324
325
326
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.
327

328
Lemma big_sepL_sep_zip {A B} (Φ1 : nat  A  PROP) (Φ2 : nat  B  PROP) l1 l2 :
Ralf Jung's avatar
Ralf Jung committed
329
  length l1 = length l2 
330
331
332
  ([ 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
333
334

Lemma big_sepL_zip_with {A B C} (Φ : nat  A  PROP) f (l1 : list B) (l2 : list C) :
335
336
  ([ 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
337
338
339
340
341
Proof.
  revert Φ l2; induction l1 as [|x l1 IH]=> Φ [|y l2] //=.
  - by rewrite big_sepL_emp left_id.
  - by rewrite IH.
Qed.
342

343
(** ** Big ops over two lists *)
344
Lemma big_sepL2_alt {A B} (Φ : nat  A  B  PROP) l1 l2 :
345
346
  ([ list] ky1;y2  l1; l2, Φ k y1 y2) 
   length l1 = length l2   [ list] k  xy  zip l1 l2, Φ k (xy.1) (xy.2).
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
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.
366
367
  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
368
369
370
371
372
373
  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.
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

  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.
439
  Lemma big_sepL2_app_inv Φ l1 l2 l1' l2' :
440
    length l1 = length l1'  length l2 = length l2' 
441
442
443
444
    ([ 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.
445
    revert Φ l1'. induction l1 as [|x1 l1 IH]=> Φ -[|x1' l1'] /= Hlen.
446
    - by rewrite left_id.
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
    - 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.
462
  Qed.
463

Ralf Jung's avatar
Ralf Jung committed
464
  Lemma big_sepL2_snoc Φ x1 x2 l1 l2 :
465
466
    ([ 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
467
  Proof.
468
469
    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
470
471
  Qed.

472
473
  (** 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. *)
474
475
476
477
478
479
480
  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.
481
482
483
484
485
486
487
  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.
488
489
490
491
492
493
494
  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 _);
      apply big_sepL2_mono; auto using equiv_entails, equiv_entails_sym.
  Qed.
495
496
497
498
499
500
501
502
503
504
505
506
507
508
  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.
509

510
  Global Instance big_sepL2_ne' n :
511
512
513
    Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (dist n)))
      ==> (=) ==> (=) ==> (dist n))
           (big_sepL2 (PROP:=PROP) (A:=A) (B:=B)).
514
  Proof. intros f g Hf l1 ? <- l2 ? <-. apply big_sepL2_ne; intros; apply Hf. Qed.
515
516
517
518
519
520
521
522
523
524
525
  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.

526
527
528
529
530
531
532
533
534
535
536
537
  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.

538
539
540
541
542
  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.
543
544
    intros. rewrite {1}big_sepL2_insert_acc // (forall_elim x1) (forall_elim x2).
    by rewrite !list_insert_id.
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
  Qed.

  Lemma big_sepL2_lookup Φ l1 l2 i x1 x2 `{!Absorbing (Φ i x1 x2)} :
    l1 !! i = Some x1  l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2)  Φ i x1 x2.
  Proof. intros. rewrite big_sepL2_lookup_acc //. by rewrite sep_elim_l. Qed.

  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.

567
568
569
570
571
572
573
574
575
576
577
  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.

578
579
580
581
582
583
584
585
586
  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.

587
  Lemma big_sepL2_sep Φ Ψ l1 l2 :
588
589
590
    ([ 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.
591
    rewrite !big_sepL2_alt big_sepL_sep !persistent_and_affinely_sep_l.
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
    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.

  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.

  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.

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
635
636
637
  Lemma big_sepL2_intuitionistically_forall Φ l1 l2 :
    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.
    intros. apply (anti_symm _).
    - apply and_intro; [apply big_sepL2_length|].
      apply forall_intro=> k. apply forall_intro=> x1. apply forall_intro=> x2.
      do 2 (apply impl_intro_l; apply pure_elim_l=> ?). by apply :big_sepL2_lookup.
    - apply pure_elim_l=> ?. rewrite -big_sepL2_intuitionistically_forall //.
      repeat setoid_rewrite pure_impl_forall.
      by rewrite intuitionistic_intuitionistically.
  Qed.

638
639
640
641
642
643
  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.
644
645
646
    rewrite -(idemp bi_and (big_sepL2 _ _ _)) {1}big_sepL2_length.
    apply pure_elim_l=> ?. rewrite big_sepL2_intuitionistically_forall //.
    apply bi.wand_intro_l. rewrite -big_sepL2_sep. by setoid_rewrite wand_elim_l.
647
648
  Qed.

649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
  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.

673
  Lemma big_sepL2_lookup_acc_impl {Φ l1 l2} i x1 x2 :
674
675
676
    l1 !! i = Some x1 
    l2 !! i = Some x2 
    ([ list] ky1;y2  l1;l2, Φ k y1 y2) -
677
678
679
680
    (* We obtain [Φ] for the [x1] and [x2] *)
    Φ i x1 x2 
    (* We reobtain the bigop for a predicate [Ψ] selected by the user *)
     Ψ,
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
       ( 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.

700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
  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.
    rewrite !big_sepL2_alt later_and big_sepL_later (timeless  _ %I).
    rewrite except_0_and. auto using and_mono, except_0_intro.
  Qed.

  Lemma big_sepL2_later_2 Φ l1 l2 :
    ([ list] ky1;y2  l1;l2,  Φ k y1 y2)   [ list] ky1;y2  l1;l2, Φ k y1 y2.
  Proof.
    rewrite !big_sepL2_alt later_and big_sepL_later_2.
    auto using and_mono, later_intro.
  Qed.

  Lemma big_sepL2_laterN_2 Φ n l1 l2 :
    ([ list] ky1;y2  l1;l2, ^n Φ k y1 y2)  ^n [ list] ky1;y2  l1;l2, Φ k y1 y2.
  Proof.
    rewrite !big_sepL2_alt laterN_and big_sepL_laterN_2.
    auto using and_mono, laterN_intro.
  Qed.

  Lemma big_sepL2_flip Φ l1 l2 :
    ([ list] ky1;y2  l2; l1, Φ k y2 y1)  ([ list] ky1;y2  l1; l2, Φ k y1 y2).
  Proof.
    revert Φ l2. induction l1 as [|x1 l1 IH]=> Φ -[|x2 l2]//=; simplify_eq.
    by rewrite IH.
  Qed.

728
  Lemma big_sepL_sepL2 (Φ1 : nat  A  PROP) (Φ2 : nat  B  PROP) l1 l2 :
Ralf Jung's avatar
Ralf Jung committed
729
    length l1 = length l2 
730
731
    ([ list] ky1;y2  l1;l2, Φ1 k y1  Φ2 k y2) 
    ([ list] ky1  l1, Φ1 k y1)  ([ list] ky2  l2, Φ2 k y2).
Ralf Jung's avatar
Ralf Jung committed
732
  Proof.
733
    intros. rewrite -big_sepL_sep_zip // big_sepL2_alt pure_True // left_id //.
Ralf Jung's avatar
Ralf Jung committed
734
  Qed.
735
736
737
738
739
740
  Lemma big_sepL_sepL2_2 (Φ1 : nat  A  PROP) (Φ2 : nat  B  PROP) l1 l2 :
    length l1 = length l2 
    ([ list] ky1  l1, Φ1 k y1) -
    ([ list] ky2  l2, Φ2 k y2) -
    [ list] ky1;y2  l1;l2, Φ1 k y1  Φ2 k y2.
  Proof. intros. apply wand_intro_r. by rewrite big_sepL_sepL2. Qed.
Ralf Jung's avatar
Ralf Jung committed
741

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
  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.
757
758
759
760
761
762
763
764

  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.
765
766
End sep_list2.

767
768
769
Lemma big_sepL_sepL2_diag {A} (Φ : nat  A  A  PROP) (l : list A) :
  ([ list] ky  l, Φ k y y) -
  ([ list] ky1;y2  l;l, Φ k y1 y2).
770
771
772
773
Proof.
  rewrite big_sepL2_alt. rewrite pure_True // left_id.
  rewrite zip_diag big_sepL_fmap /=. done.
Qed.
774

775
Lemma big_sepL2_ne_2 {A B : ofe}
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
    (Φ Ψ : nat  A  B  PROP) l1 l2 l1' l2' n :
  l1 {n} l1'  l2 {n} l2' 
  ( k y1 y1' y2 y2',
    l1 !! k = Some y1  l1' !! k = Some y1'  y1 {n} y1' 
    l2 !! k = Some y2  l2' !! k = Some y2'  y2 {n} 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 Hl1 Hl2 Hf. rewrite !big_sepL2_alt. f_equiv.
  { do 2 f_equiv; by apply: length_ne. }
  apply big_opL_ne_2; [by f_equiv|].
  intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%lookup_zip_with_Some
    (?&?&[=<- <-]&?&?)%lookup_zip_with_Some [??]; naive_solver.
Qed.

791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
Section and_list.
  Context {A : Type}.
  Implicit Types l : list A.
  Implicit Types Φ Ψ : nat  A  PROP.

  Lemma big_andL_nil Φ : ([ list] ky  nil, Φ k y)  True.
  Proof. done. Qed.
  Lemma big_andL_nil' P Φ : P  [ list] ky  nil, Φ k y.
  Proof. by apply pure_intro. Qed.
  Lemma big_andL_cons Φ x l :
    ([ list] ky  x :: l, Φ k y)  Φ 0 x  [ list] ky  l, Φ (S k) y.
  Proof. by rewrite big_opL_cons. Qed.
  Lemma big_andL_singleton Φ x : ([ list] ky  [x], Φ k y)  Φ 0 x.
  Proof. by rewrite big_opL_singleton. Qed.
  Lemma big_andL_app Φ l1 l2 :
    ([ list] ky  l1 ++ l2, Φ k y)
     ([ list] ky  l1, Φ k y)  ([ list] ky  l2, Φ (length l1 + k) y).
  Proof. by rewrite big_opL_app. Qed.

810
811
812
813
814
815
816
817
  Lemma big_andL_submseteq (Φ : A  PROP) l1 l2 :
    l1 + l2  ([ list] y  l2, Φ y)  [ list] y  l1, Φ y.
  Proof.
    intros [l ->]%submseteq_Permutation. by rewrite big_andL_app and_elim_l.
  Qed.

  (** The lemmas [big_andL_mono], [big_andL_ne] and [big_andL_proper] are more
  generic than the instances as they also give [l !! k = Some y] in the premise. *)
818
819
820
  Lemma big_andL_mono Φ Ψ l :
    ( k y, l !! k = Some y  Φ k y  Ψ k y) 
    ([ list] k  y  l, Φ k y)  [ list] k  y  l, Ψ k y.
821
  Proof. apply big_opL_gen_proper; apply _. Qed.
822
823
824
825
  Lemma big_andL_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.
826
827
828
829
830
  Lemma big_andL_proper Φ Ψ l :
    ( k y, l !! k = Some y  Φ k y  Ψ k y) 
    ([ list] k  y  l, Φ k y)  ([ list] k  y  l, Ψ k y).
  Proof. apply big_opL_proper. Qed.

831
832
  (** No need to declare instances for non-expansiveness and properness, we
  get both from the generic [big_opL] instances. *)
833
834
835
  Global Instance big_andL_mono' :
    Proper (pointwise_relation _ (pointwise_relation _ ()) ==> (=) ==> ())
           (big_opL (@bi_and PROP) (A:=A)).
836
  Proof. intros f g Hf m ? <-. apply big_andL_mono; intros; apply Hf. Qed.
837
  Global Instance big_andL_id_mono' :
838
    Proper (Forall2 () ==> ()) (big_opL (@bi_and PROP) (λ _ P, P)).
839
840
  Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed.

841
  Lemma big_andL_lookup Φ l i x :
842
843
844
845
846
847
848
    l !! i = Some x  ([ list] ky  l, Φ k y)  Φ i x.
  Proof.
    intros. rewrite -(take_drop_middle l i x) // big_andL_app /=.
    rewrite Nat.add_0_r take_length_le;
      eauto using lookup_lt_Some, Nat.lt_le_incl, and_elim_l', and_elim_r'.
  Qed.

849
  Lemma big_andL_elem_of (Φ : A  PROP) l x :
850
851
    x  l  ([ list] y  l, Φ y)  Φ x.
  Proof.
Robbert Krebbers's avatar
Robbert Krebbers committed
852
    intros [i ?]%elem_of_list_lookup. by eapply (big_andL_lookup (λ _, Φ)).
853
854
855
856
857
858
  Qed.

  Lemma big_andL_fmap {B} (f : A  B) (Φ : nat  B  PROP) l :
    ([ list] ky  f <$> l, Φ k y)  ([ list] ky  l, Φ k (f y)).
  Proof. by rewrite big_opL_fmap. Qed.

859
860
861
862
  Lemma big_andL_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.

863
864
  Lemma big_andL_and Φ Ψ l :
    ([ list] kx  l, Φ k x  Ψ k x)
865
866
     ([ list] kx  l, Φ k x)  ([ list] kx  l, Ψ k x).
  Proof. by rewrite big_opL_op. Qed.
867
868

  Lemma big_andL_persistently Φ l :
869
    <pers> ([ list] kx  l, Φ k x)  [ list] kx  l, <pers> (Φ k x).
870
871
  Proof. apply (big_opL_commute _). Qed.