diff --git a/theories/algebra/big_op.v b/theories/algebra/big_op.v index d7f86c27dffb69ce6d0468d45c3b8182c37a8d94..7bf52ebc2d90a1bb6b37f59afb9d85c6563752cd 100644 --- a/theories/algebra/big_op.v +++ b/theories/algebra/big_op.v @@ -101,23 +101,36 @@ Section list. Lemma big_opL_unit l : ([^o list] k↦y ∈ l, monoid_unit) ≡ (monoid_unit : M). Proof. induction l; rewrite /= ?left_id //. Qed. - Lemma big_opL_forall R f g l : + Lemma big_opL_gen_proper_2 (R : relation M) f g l1 l2 : + R monoid_unit monoid_unit → + Proper (R ==> R ==> R) o → + (∀ k, + match l1 !! k, l2 !! k with + | Some y1, Some y2 => R (f k y1) (g k y2) + | None, None => True + | _, _ => False + end) → + R ([^o list] k ↦ y ∈ l1, f k y) ([^o list] k ↦ y ∈ l2, g k y). + Proof. + intros ??. revert l2 f g. induction l1 as [|x1 l1 IH]=> -[|x2 l2] //= f g Hfg. + - by specialize (Hfg 0). + - by specialize (Hfg 0). + - f_equiv; [apply (Hfg 0)|]. apply IH. intros k. apply (Hfg (S k)). + Qed. + Lemma big_opL_gen_proper R f g l : Reflexive R → Proper (R ==> R ==> R) o → (∀ k y, l !! k = Some y → R (f k y) (g k y)) → R ([^o list] k ↦ y ∈ l, f k y) ([^o list] k ↦ y ∈ l, g k y). Proof. - intros ??. revert f g. induction l as [|x l IH]=> f g ? //=; f_equiv; eauto. + intros. apply big_opL_gen_proper_2; [done..|]. + intros k. destruct (l !! k) eqn:?; auto. Qed. Lemma big_opL_ext f g l : (∀ k y, l !! k = Some y → f k y = g k y) → ([^o list] k ↦ y ∈ l, f k y) = [^o list] k ↦ y ∈ l, g k y. - Proof. apply big_opL_forall; apply _. Qed. - Lemma big_opL_proper f g l : - (∀ k y, l !! k = Some y → f k y ≡ g k y) → - ([^o list] k ↦ y ∈ l, f k y) ≡ ([^o list] k ↦ y ∈ l, g k y). - Proof. apply big_opL_forall; apply _. Qed. + Proof. apply big_opL_gen_proper; apply _. Qed. Lemma big_opL_permutation (f : A → M) l1 l2 : l1 ≡ₚ l2 → ([^o list] x ∈ l1, f x) ≡ ([^o list] x ∈ l2, f x). @@ -131,14 +144,41 @@ Section list. Proper ((≡ₚ) ==> (≡)) (big_opL o (λ _, f)). Proof. intros xs1 xs2. apply big_opL_permutation. Qed. - Global Instance big_opL_ne n : + (** The lemmas [big_opL_ne] and [big_opL_proper] are more generic than the + instances as they also give [l !! k = Some y] in the premise. *) + Lemma big_opL_ne f g l n : + (∀ k y, l !! k = Some y → f k y ≡{n}≡ g k y) → + ([^o list] k ↦ y ∈ l, f k y) ≡{n}≡ ([^o list] k ↦ y ∈ l, g k y). + Proof. apply big_opL_gen_proper; apply _. Qed. + Lemma big_opL_proper f g l : + (∀ k y, l !! k = Some y → f k y ≡ g k y) → + ([^o list] k ↦ y ∈ l, f k y) ≡ ([^o list] k ↦ y ∈ l, g k y). + Proof. apply big_opL_gen_proper; apply _. Qed. + + (** The version [big_opL_proper_2] with [≡] for the list arguments can only be + used if there is a setoid on [A]. The version for [dist n] can be found in + [algebra.list]. We do not define this lemma as a [Proper] instance, since + [f_equiv] will then use sometimes use this one, and other times + [big_opL_proper'], depending on whether a setoid on [A] exists. *) + Lemma big_opL_proper_2 `{!Equiv A} f g l1 l2 : + l1 ≡ l2 → + (∀ k y1 y2, + l1 !! k = Some y1 → l2 !! k = Some y2 → y1 ≡ y2 → f k y1 ≡ g k y2) → + ([^o list] k ↦ y ∈ l1, f k y) ≡ ([^o list] k ↦ y ∈ l2, g k y). + Proof. + intros Hl Hf. apply big_opL_gen_proper_2; try (apply _ || done). + intros k. assert (l1 !! k ≡ l2 !! k) as Hlk by (by f_equiv). + destruct (l1 !! k) eqn:?, (l2 !! k) eqn:?; inversion Hlk; naive_solver. + Qed. + + Global Instance big_opL_ne' n : Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (=) ==> dist n) (big_opL o (A:=A)). - Proof. intros f f' Hf l ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f f' Hf l ? <-. apply big_opL_ne; intros; apply Hf. Qed. Global Instance big_opL_proper' : Proper (pointwise_relation _ (pointwise_relation _ (≡)) ==> (=) ==> (≡)) (big_opL o (A:=A)). - Proof. intros f f' Hf l ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f f' Hf l ? <-. apply big_opL_proper; intros; apply Hf. Qed. Lemma big_opL_consZ_l (f : Z → A → M) x l : ([^o list] k↦y ∈ x :: l, f k y) = f 0 x `o` [^o list] k↦y ∈ l, f (1 + k)%Z y. @@ -172,48 +212,96 @@ Section gmap. Implicit Types m : gmap K A. Implicit Types f g : K → A → M. - Lemma big_opM_forall R f g m : - Reflexive R → Proper (R ==> R ==> R) o → + Lemma big_opM_empty f : ([^o map] k↦x ∈ ∅, f k x) = monoid_unit. + Proof. by rewrite big_opM_eq /big_opM_def map_to_list_empty. Qed. + + Lemma big_opM_insert f m i x : + m !! i = None → + ([^o map] k↦y ∈ <[i:=x]> m, f k y) ≡ f i x `o` [^o map] k↦y ∈ m, f k y. + Proof. intros ?. by rewrite big_opM_eq /big_opM_def map_to_list_insert. Qed. + + Lemma big_opM_delete f m i x : + m !! i = Some x → + ([^o map] k↦y ∈ m, f k y) ≡ f i x `o` [^o map] k↦y ∈ delete i m, f k y. + Proof. + intros. rewrite -big_opM_insert ?lookup_delete //. + by rewrite insert_delete insert_id. + Qed. + + Lemma big_opM_gen_proper_2 (R : relation M) f g m1 m2 : + subrelation (≡) R → Equivalence R → + Proper (R ==> R ==> R) o → + (∀ k, + match m1 !! k, m2 !! k with + | Some y1, Some y2 => R (f k y1) (g k y2) + | None, None => True + | _, _ => False + end) → + R ([^o map] k ↦ x ∈ m1, f k x) ([^o map] k ↦ x ∈ m2, g k x). + Proof. + intros HR ??. revert m2 f g. + induction m1 as [|k x1 m1 Hm1k IH] using map_ind=> m2 f g Hfg. + { destruct m2 as [|k x2 m2 _ _] using map_ind. + { rewrite !big_opM_empty. by apply HR. } + generalize (Hfg k). by rewrite lookup_empty lookup_insert. } + generalize (Hfg k). rewrite lookup_insert. + destruct (m2 !! k) as [x2|] eqn:Hm2k; [intros Hk|done]. + etrans; [by apply HR, big_opM_insert|]. + etrans; [|by symmetry; apply HR, big_opM_delete]. + f_equiv; [done|]. apply IH=> k'. destruct (decide (k = k')) as [->|?]. + - by rewrite lookup_delete Hm1k. + - generalize (Hfg k'). rewrite lookup_insert_ne // lookup_delete_ne //. + Qed. + + Lemma big_opM_gen_proper R f g m : + Reflexive R → + Proper (R ==> R ==> R) o → (∀ k x, m !! k = Some x → R (f k x) (g k x)) → R ([^o map] k ↦ x ∈ m, f k x) ([^o map] k ↦ x ∈ m, g k x). Proof. - intros ?? Hf. rewrite big_opM_eq. apply (big_opL_forall R); auto. + intros ?? Hf. rewrite big_opM_eq. apply (big_opL_gen_proper R); auto. intros k [i x] ?%elem_of_list_lookup_2. by apply Hf, elem_of_map_to_list. Qed. Lemma big_opM_ext f g m : (∀ k x, m !! k = Some x → f k x = g k x) → ([^o map] k ↦ x ∈ m, f k x) = ([^o map] k ↦ x ∈ m, g k x). - Proof. apply big_opM_forall; apply _. Qed. + Proof. apply big_opM_gen_proper; apply _. Qed. + + (** The lemmas [big_opM_ne] and [big_opM_proper] are more generic than the + instances as they also give [m !! k = Some y] in the premise. *) + Lemma big_opM_ne f g m n : + (∀ k x, m !! k = Some x → f k x ≡{n}≡ g k x) → + ([^o map] k ↦ x ∈ m, f k x) ≡{n}≡ ([^o map] k ↦ x ∈ m, g k x). + Proof. apply big_opM_gen_proper; apply _. Qed. Lemma big_opM_proper f g m : (∀ k x, m !! k = Some x → f k x ≡ g k x) → ([^o map] k ↦ x ∈ m, f k x) ≡ ([^o map] k ↦ x ∈ m, g k x). - Proof. apply big_opM_forall; apply _. Qed. + Proof. apply big_opM_gen_proper; apply _. Qed. + (** The version [big_opL_proper_2] with [≡] for the map arguments can only be + used if there is a setoid on [A]. The version for [dist n] can be found in + [algebra.gmap]. We do not define this lemma as a [Proper] instance, since + [f_equiv] will then use sometimes use this one, and other times + [big_opM_proper'], depending on whether a setoid on [A] exists. *) + Lemma big_opM_proper_2 `{!Equiv A} f g m1 m2 : + m1 ≡ m2 → + (∀ k y1 y2, + m1 !! k = Some y1 → m2 !! k = Some y2 → y1 ≡ y2 → f k y1 ≡ g k y2) → + ([^o map] k ↦ y ∈ m1, f k y) ≡ ([^o map] k ↦ y ∈ m2, g k y). + Proof. + intros Hl Hf. apply big_opM_gen_proper_2; try (apply _ || done). + intros k. assert (m1 !! k ≡ m2 !! k) as Hlk by (by f_equiv). + destruct (m1 !! k) eqn:?, (m2 !! k) eqn:?; inversion Hlk; naive_solver. + Qed. - Global Instance big_opM_ne n : + Global Instance big_opM_ne' n : Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (=) ==> dist n) (big_opM o (K:=K) (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opM_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_opM_ne; intros; apply Hf. Qed. Global Instance big_opM_proper' : Proper (pointwise_relation _ (pointwise_relation _ (≡)) ==> (=) ==> (≡)) (big_opM o (K:=K) (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opM_forall; apply _ || intros; apply Hf. Qed. - - Lemma big_opM_empty f : ([^o map] k↦x ∈ ∅, f k x) = monoid_unit. - Proof. by rewrite big_opM_eq /big_opM_def map_to_list_empty. Qed. - - Lemma big_opM_insert f m i x : - m !! i = None → - ([^o map] k↦y ∈ <[i:=x]> m, f k y) ≡ f i x `o` [^o map] k↦y ∈ m, f k y. - Proof. intros ?. by rewrite big_opM_eq /big_opM_def map_to_list_insert. Qed. - - Lemma big_opM_delete f m i x : - m !! i = Some x → - ([^o map] k↦y ∈ m, f k y) ≡ f i x `o` [^o map] k↦y ∈ delete i m, f k y. - Proof. - intros. rewrite -big_opM_insert ?lookup_delete //. - by rewrite insert_delete insert_id. - Qed. + Proof. intros f g Hf m ? <-. apply big_opM_proper; intros; apply Hf. Qed. Lemma big_opM_singleton f i x : ([^o map] k↦y ∈ {[i:=x]}, f k y) ≡ f i x. Proof. @@ -278,30 +366,37 @@ Section gset. Implicit Types X : gset A. Implicit Types f : A → M. - Lemma big_opS_forall R f g X : + Lemma big_opS_gen_proper R f g X : Reflexive R → Proper (R ==> R ==> R) o → (∀ x, x ∈ X → R (f x) (g x)) → R ([^o set] x ∈ X, f x) ([^o set] x ∈ X, g x). Proof. - rewrite big_opS_eq. intros ?? Hf. apply (big_opL_forall R); auto. + rewrite big_opS_eq. intros ?? Hf. apply (big_opL_gen_proper R); auto. intros k x ?%elem_of_list_lookup_2. by apply Hf, elem_of_elements. Qed. Lemma big_opS_ext f g X : (∀ x, x ∈ X → f x = g x) → ([^o set] x ∈ X, f x) = ([^o set] x ∈ X, g x). - Proof. apply big_opS_forall; apply _. Qed. + Proof. apply big_opS_gen_proper; apply _. Qed. + + (** The lemmas [big_opS_ne] and [big_opS_proper] are more generic than the + instances as they also give [x ∈ X] in the premise. *) + Lemma big_opS_ne f g X n : + (∀ x, x ∈ X → f x ≡{n}≡ g x) → + ([^o set] x ∈ X, f x) ≡{n}≡ ([^o set] x ∈ X, g x). + Proof. apply big_opS_gen_proper; apply _. Qed. Lemma big_opS_proper f g X : (∀ x, x ∈ X → f x ≡ g x) → ([^o set] x ∈ X, f x) ≡ ([^o set] x ∈ X, g x). - Proof. apply big_opS_forall; apply _. Qed. + Proof. apply big_opS_gen_proper; apply _. Qed. - Global Instance big_opS_ne n : + Global Instance big_opS_ne' n : Proper (pointwise_relation _ (dist n) ==> (=) ==> dist n) (big_opS o (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opS_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_opS_ne; intros; apply Hf. Qed. Global Instance big_opS_proper' : Proper (pointwise_relation _ (≡) ==> (=) ==> (≡)) (big_opS o (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opS_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_opS_proper; intros; apply Hf. Qed. Lemma big_opS_empty f : ([^o set] x ∈ ∅, f x) = monoid_unit. Proof. by rewrite big_opS_eq /big_opS_def elements_empty. Qed. @@ -365,30 +460,37 @@ Section gmultiset. Implicit Types X : gmultiset A. Implicit Types f : A → M. - Lemma big_opMS_forall R f g X : + Lemma big_opMS_gen_proper R f g X : Reflexive R → Proper (R ==> R ==> R) o → (∀ x, x ∈ X → R (f x) (g x)) → R ([^o mset] x ∈ X, f x) ([^o mset] x ∈ X, g x). Proof. - rewrite big_opMS_eq. intros ?? Hf. apply (big_opL_forall R); auto. + rewrite big_opMS_eq. intros ?? Hf. apply (big_opL_gen_proper R); auto. intros k x ?%elem_of_list_lookup_2. by apply Hf, gmultiset_elem_of_elements. Qed. Lemma big_opMS_ext f g X : (∀ x, x ∈ X → f x = g x) → ([^o mset] x ∈ X, f x) = ([^o mset] x ∈ X, g x). - Proof. apply big_opMS_forall; apply _. Qed. + Proof. apply big_opMS_gen_proper; apply _. Qed. + + (** The lemmas [big_opMS_ne] and [big_opMS_proper] are more generic than the + instances as they also give [x ∈ X] in the premise. *) + Lemma big_opMS_ne f g X n : + (∀ x, x ∈ X → f x ≡{n}≡ g x) → + ([^o mset] x ∈ X, f x) ≡{n}≡ ([^o mset] x ∈ X, g x). + Proof. apply big_opMS_gen_proper; apply _. Qed. Lemma big_opMS_proper f g X : (∀ x, x ∈ X → f x ≡ g x) → ([^o mset] x ∈ X, f x) ≡ ([^o mset] x ∈ X, g x). - Proof. apply big_opMS_forall; apply _. Qed. + Proof. apply big_opMS_gen_proper; apply _. Qed. - Global Instance big_opMS_ne n : + Global Instance big_opMS_ne' n : Proper (pointwise_relation _ (dist n) ==> (=) ==> dist n) (big_opMS o (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opMS_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_opMS_ne; intros; apply Hf. Qed. Global Instance big_opMS_proper' : Proper (pointwise_relation _ (≡) ==> (=) ==> (≡)) (big_opMS o (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opMS_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_opMS_proper; intros; apply Hf. Qed. Lemma big_opMS_empty f : ([^o mset] x ∈ ∅, f x) = monoid_unit. Proof. by rewrite big_opMS_eq /big_opMS_def gmultiset_elements_empty. Qed. diff --git a/theories/algebra/gmap.v b/theories/algebra/gmap.v index 25bc95c5b11171ea68209a004f7a8a9fa8cab7d2..d499dfa7db0c15fe543000009094b351e4ecf2fb 100644 --- a/theories/algebra/gmap.v +++ b/theories/algebra/gmap.v @@ -44,32 +44,28 @@ Proof. intros ? m m' ? i. by apply (discrete _). Qed. Global Instance gmapO_leibniz: LeibnizEquiv A → LeibnizEquiv gmapO. Proof. intros; change (LeibnizEquiv (gmap K A)); apply _. Qed. -Global Instance lookup_ne k : - NonExpansive (lookup k : gmap K A → option A). +Global Instance lookup_ne k : NonExpansive (lookup k : gmap K A → option A). Proof. by intros m1 m2. Qed. -Global Instance lookup_proper k : - Proper ((≡) ==> (≡)) (lookup k : gmap K A → option A) := _. -Global Instance alter_ne (f : A → A) (k : K) n : - Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (alter f k). +Global Instance partial_alter_ne n : + Proper ((dist n ==> dist n) ==> (=) ==> dist n ==> dist n) + (partial_alter (M:=gmap K A)). Proof. - intros ? m m' Hm k'. - by destruct (decide (k = k')); simplify_map_eq; rewrite (Hm k'). -Qed. -Global Instance insert_ne i : - NonExpansive2 (insert (M:=gmap K A) i). -Proof. - intros n x y ? m m' ? j; destruct (decide (i = j)); simplify_map_eq; - [by constructor|by apply lookup_ne]. + by intros f1 f2 Hf i ? <- m1 m2 Hm j; destruct (decide (i = j)) as [->|]; + rewrite ?lookup_partial_alter ?lookup_partial_alter_ne //; + try apply Hf; apply lookup_ne. Qed. -Global Instance singleton_ne i : - NonExpansive (singletonM i : A → gmap K A). +Global Instance insert_ne i : NonExpansive2 (insert (M:=gmap K A) i). +Proof. intros n x y ? m m' ? j; apply partial_alter_ne; by try constructor. Qed. +Global Instance singleton_ne i : NonExpansive (singletonM i : A → gmap K A). Proof. by intros ????; apply insert_ne. Qed. -Global Instance delete_ne i : - NonExpansive (delete (M:=gmap K A) i). +Global Instance delete_ne i : NonExpansive (delete (M:=gmap K A) i). Proof. intros n m m' ? j; destruct (decide (i = j)); simplify_map_eq; [by constructor|by apply lookup_ne]. Qed. +Global Instance alter_ne (f : A → A) (k : K) n : + Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (alter f k). +Proof. intros ? m m' Hm k'. by apply partial_alter_ne; [solve_proper|..]. Qed. Global Instance gmap_empty_discrete : Discrete (∅ : gmap K A). Proof. @@ -99,6 +95,63 @@ End cofe. Arguments gmapO _ {_ _} _. +(** Non-expansiveness of higher-order map functions and big-ops *) +Lemma merge_ne `{Countable K} {A B C : ofeT} (f g : option A → option B → option C) + `{!DiagNone f, !DiagNone g} n : + ((dist n) ==> (dist n) ==> (dist n))%signature f g → + ((dist n) ==> (dist n) ==> (dist n))%signature (merge (M:=gmap K) f) (merge g). +Proof. by intros Hf ?? Hm1 ?? Hm2 i; rewrite !lookup_merge //; apply Hf. Qed. +Instance union_with_proper `{Countable K} {A : ofeT} n : + Proper (((dist n) ==> (dist n) ==> (dist n)) ==> + (dist n) ==> (dist n) ==>(dist n)) (union_with (M:=gmap K A)). +Proof. + intros ?? Hf ?? Hm1 ?? Hm2 i; apply (merge_ne _ _); auto. + by do 2 destruct 1; first [apply Hf | constructor]. +Qed. +Instance map_fmap_proper `{Countable K} {A B : ofeT} (f : A → B) n : + Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (fmap (M:=gmap K) f). +Proof. intros ? m m' ? k; rewrite !lookup_fmap. by repeat f_equiv. Qed. +Instance map_zip_with_proper `{Countable K} {A B C : ofeT} (f : A → B → C) n : + Proper (dist n ==> dist n ==> dist n) f → + Proper (dist n ==> dist n ==> dist n) (map_zip_with (M:=gmap K) f). +Proof. + intros Hf m1 m1' Hm1 m2 m2' Hm2. apply merge_ne; try done. + destruct 1; destruct 1; repeat f_equiv; constructor || done. +Qed. + +Lemma big_opM_ne_2 `{Monoid M o} `{Countable K} {A : ofeT} (f g : K → A → M) m1 m2 n : + m1 ≡{n}≡ m2 → + (∀ k y1 y2, + m1 !! k = Some y1 → m2 !! k = Some y2 → y1 ≡{n}≡ y2 → f k y1 ≡{n}≡ g k y2) → + ([^o map] k ↦ y ∈ m1, f k y) ≡{n}≡ ([^o map] k ↦ y ∈ m2, g k y). +Proof. + intros Hl Hf. apply big_opM_gen_proper_2; try (apply _ || done). + { by intros ?? ->. } + { apply monoid_ne. } + intros k. assert (m1 !! k ≡{n}≡ m2 !! k) as Hlk by (by f_equiv). + destruct (m1 !! k) eqn:?, (m2 !! k) eqn:?; inversion Hlk; naive_solver. +Qed. + +Lemma big_sepM2_ne_2 {PROP : bi} `{Countable K} (A B : ofeT) + (Φ Ψ : K → A → B → PROP) m1 m2 m1' m2' n : + m1 ≡{n}≡ m1' → m2 ≡{n}≡ m2' → + (∀ k y1 y1' y2 y2', + m1 !! k = Some y1 → m1' !! k = Some y1' → y1 ≡{n}≡ y1' → + m2 !! k = Some y2 → m2' !! k = Some y2' → y2 ≡{n}≡ y2' → + Φ k y1 y2 ≡{n}≡ Ψ k y1' y2') → + ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2)%I ≡{n}≡ ([∗ map] k ↦ y1;y2 ∈ m1';m2', Ψ k y1 y2)%I. +Proof. + intros Hm1 Hm2 Hf. rewrite big_sepM2_eq /big_sepM2_def. f_equiv. + { f_equiv; split; intros Hm k. + - trans (is_Some (m1 !! k)); [symmetry; apply: is_Some_ne; by f_equiv|]. + rewrite Hm. apply: is_Some_ne; by f_equiv. + - trans (is_Some (m1' !! k)); [apply: is_Some_ne; by f_equiv|]. + rewrite Hm. symmetry. apply: is_Some_ne; by f_equiv. } + apply big_opM_ne_2; [by f_equiv|]. + intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some + (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some [??]; naive_solver. +Qed. + (* CMRA *) Section cmra. Context `{Countable K} {A : cmraT}. diff --git a/theories/algebra/list.v b/theories/algebra/list.v index 6325e1716d5040c61c7c9c4adca7fc6c32adea7b..669500516482021e9b5cff81e849443ebc3900b2 100644 --- a/theories/algebra/list.v +++ b/theories/algebra/list.v @@ -94,13 +94,64 @@ End cofe. Arguments listO : clear implicits. +(** Non-expansiveness of higher-order list functions and big-ops *) +Instance list_fmap_ne {A B : ofeT} (f : A → B) n : + Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (fmap (M:=list) f). +Proof. intros Hf l k ?; by eapply Forall2_fmap, Forall2_impl; eauto. Qed. +Instance list_omap_ne {A B : ofeT} (f : A → option B) n : + Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (omap (M:=list) f). +Proof. + intros Hf. induction 1 as [|x1 x2 l1 l2 Hx Hl]; csimpl; [constructor|]. + destruct (Hf _ _ Hx); [f_equiv|]; auto. +Qed. +Instance imap_ne {A B : ofeT} (f : nat → A → B) n : + (∀ i, Proper (dist n ==> dist n) (f i)) → Proper (dist n ==> dist n) (imap f). +Proof. + intros Hf l1 l2 Hl. revert f Hf. + induction Hl; intros f Hf; simpl; [constructor|f_equiv; naive_solver]. +Qed. +Instance list_bind_ne {A B : ofeT} (f : A → list A) n : + Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (mbind f). +Proof. induction 2; simpl; [constructor|solve_proper]. Qed. +Instance list_join_ne {A : ofeT} : NonExpansive (mjoin (M:=list) (A:=A)). +Proof. induction 1; simpl; [constructor|solve_proper]. Qed. +Instance zip_with_ne {A B C : ofeT} (f : A → B → C) : + Proper (dist n ==> dist n ==> dist n) f → + Proper (dist n ==> dist n ==> dist n) (zip_with f). +Proof. induction 2; destruct 1; simpl; [constructor..|f_equiv; [f_equiv|]; auto]. Qed. + +Lemma big_opL_ne_2 `{Monoid M o} {A : ofeT} (f g : nat → A → M) l1 l2 n : + l1 ≡{n}≡ l2 → + (∀ k y1 y2, + l1 !! k = Some y1 → l2 !! k = Some y2 → y1 ≡{n}≡ y2 → f k y1 ≡{n}≡ g k y2) → + ([^o list] k ↦ y ∈ l1, f k y) ≡{n}≡ ([^o list] k ↦ y ∈ l2, g k y). +Proof. + intros Hl Hf. apply big_opL_gen_proper_2; try (apply _ || done). + { apply monoid_ne. } + intros k. assert (l1 !! k ≡{n}≡ l2 !! k) as Hlk by (by f_equiv). + destruct (l1 !! k) eqn:?, (l2 !! k) eqn:?; inversion Hlk; naive_solver. +Qed. + +Lemma big_sepL2_ne_2 {PROP : bi} {A B : ofeT} + (Φ Ψ : 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. + (** Functor *) Lemma list_fmap_ext_ne {A} {B : ofeT} (f g : A → B) (l : list A) n : (∀ x, f x ≡{n}≡ g x) → f <$> l ≡{n}≡ g <$> l. Proof. intros Hf. by apply Forall2_fmap, Forall_Forall2, Forall_true. Qed. -Instance list_fmap_ne {A B : ofeT} (f : A → B) n: - Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (fmap (M:=list) f). -Proof. intros Hf l k ?; by eapply Forall2_fmap, Forall2_impl; eauto. Qed. Definition listO_map {A B} (f : A -n> B) : listO A -n> listO B := OfeMor (fmap f : listO A → listO B). Instance listO_map_ne A B : NonExpansive (@listO_map A B). diff --git a/theories/bi/big_op.v b/theories/bi/big_op.v index 491596e320a6569b84e2462980ec712c5b9a915c..6f57d7fc50db7e479f63ad89efe94a99ccbd6606 100644 --- a/theories/bi/big_op.v +++ b/theories/bi/big_op.v @@ -91,24 +91,33 @@ Section sep_list. ⊣⊢ ([∗ list] k↦y ∈ l1, Φ k y) ∗ ([∗ list] k↦y ∈ l2, Φ (length l1 + k) y). Proof. by rewrite big_opL_app. Qed. + 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. *) Lemma big_sepL_mono Φ Ψ 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_forall; apply _. Qed. + Proof. apply big_opL_gen_proper; apply _. Qed. + 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. Lemma big_sepL_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. - 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. + (** No need to declare instances for non-expansiveness and properness, we + get both from the generic [big_opL] instances. *) Global Instance big_sepL_mono' : Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢)) (big_opL (@bi_sep PROP) (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_sepL_mono; intros; apply Hf. Qed. Global Instance big_sepL_id_mono' : Proper (Forall2 (⊢) ==> (⊢)) (big_opL (@bi_sep PROP) (λ _ P, P)). Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed. @@ -349,6 +358,8 @@ Section sep_list2. - by rewrite -assoc IH. Qed. + (** 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. *) 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. @@ -356,6 +367,13 @@ Section sep_list2. intros H. rewrite !big_sepL2_alt. f_equiv. apply big_sepL_mono=> k [y1 y2]. rewrite lookup_zip_with=> ?; simplify_option_eq; auto. Qed. + 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. 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. @@ -363,15 +381,26 @@ Section sep_list2. intros; apply (anti_symm _); apply big_sepL2_mono; auto using equiv_entails, equiv_entails_sym. Qed. + 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. - Global Instance big_sepL2_ne n : + Global Instance big_sepL2_ne' n : Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (dist n))) ==> (=) ==> (=) ==> (dist n)) (big_sepL2 (PROP:=PROP) (A:=A) (B:=B)). - Proof. - intros Φ1 Φ2 HΦ x1 ? <- x2 ? <-. rewrite !big_sepL2_alt. f_equiv. - f_equiv=> k [y1 y2]. apply HΦ. - Qed. + Proof. intros f g Hf l1 ? <- l2 ? <-. apply big_sepL2_ne; intros; apply Hf. Qed. Global Instance big_sepL2_mono' : Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (⊢))) ==> (=) ==> (=) ==> (⊢)) @@ -499,24 +528,33 @@ Section and_list. ⊣⊢ ([∧ list] k↦y ∈ l1, Φ k y) ∧ ([∧ list] k↦y ∈ l2, Φ (length l1 + k) y). Proof. by rewrite big_opL_app. Qed. + 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. *) 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. - Proof. apply big_opL_forall; apply _. Qed. + Proof. apply big_opL_gen_proper; apply _. Qed. + 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. 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. - 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. + (** No need to declare instances for non-expansiveness and properness, we + get both from the generic [big_opL] instances. *) Global Instance big_andL_mono' : Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢)) (big_opL (@bi_and PROP) (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_andL_mono; intros; apply Hf. Qed. Global Instance big_andL_id_mono' : Proper (Forall2 (⊢) ==> (⊢)) (big_opL (@bi_and PROP) (λ _ P, P)). Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed. @@ -589,24 +627,33 @@ Section or_list. ⊣⊢ ([∨ list] k↦y ∈ l1, Φ k y) ∨ ([∨ list] k↦y ∈ l2, Φ (length l1 + k) y). Proof. by rewrite big_opL_app. Qed. + Lemma big_orL_submseteq (Φ : A → PROP) l1 l2 : + l1 ⊆+ l2 → ([∨ list] y ∈ l1, Φ y) ⊢ [∨ list] y ∈ l2, Φ y. + Proof. + intros [l ->]%submseteq_Permutation. by rewrite big_orL_app -or_intro_l. + Qed. + + (** The lemmas [big_orL_mono], [big_orL_ne] and [big_orL_proper] are more + generic than the instances as they also give [l !! k = Some y] in the premise. *) Lemma big_orL_mono Φ Ψ 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_forall; apply _. Qed. + Proof. apply big_opL_gen_proper; apply _. Qed. + Lemma big_orL_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. Lemma big_orL_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. - Lemma big_orL_submseteq (Φ : A → PROP) l1 l2 : - l1 ⊆+ l2 → ([∨ list] y ∈ l1, Φ y) ⊢ [∨ list] y ∈ l2, Φ y. - Proof. - intros [l ->]%submseteq_Permutation. by rewrite big_orL_app -or_intro_l. - Qed. + (** No need to declare instances for non-expansiveness and properness, we + get both from the generic [big_opL] instances. *) Global Instance big_orL_mono' : Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢)) (big_opL (@bi_or PROP) (A:=A)). - Proof. intros f g Hf m ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_orL_mono; intros; apply Hf. Qed. Global Instance big_orL_id_mono' : Proper (Forall2 (⊢) ==> (⊢)) (big_opL (@bi_or PROP) (λ _ P, P)). Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed. @@ -680,22 +727,31 @@ Section map. Implicit Types m : gmap K A. Implicit Types Φ Ψ : K → A → PROP. + Lemma big_sepM_subseteq `{BiAffine PROP} Φ m1 m2 : + m2 ⊆ m1 → ([∗ map] k ↦ x ∈ m1, Φ k x) ⊢ [∗ map] k ↦ x ∈ m2, Φ k x. + Proof. rewrite big_opM_eq. intros. by apply big_sepL_submseteq, map_to_list_submseteq. Qed. + + (** The lemmas [big_sepM_mono], [big_sepM_ne] and [big_sepM_proper] are more + generic than the instances as they also give [l !! k = Some y] in the premise. *) Lemma big_sepM_mono Φ Ψ m : (∀ k x, m !! k = Some x → Φ k x ⊢ Ψ k x) → ([∗ map] k ↦ x ∈ m, Φ k x) ⊢ [∗ map] k ↦ x ∈ m, Ψ k x. - Proof. apply big_opM_forall; apply _ || auto. Qed. + Proof. apply big_opM_gen_proper; apply _ || auto. Qed. + Lemma big_sepM_ne Φ Ψ m n : + (∀ k x, m !! k = Some x → Φ k x ≡{n}≡ Ψ k x) → + ([∗ map] k ↦ x ∈ m, Φ k x)%I ≡{n}≡ ([∗ map] k ↦ x ∈ m, Ψ k x)%I. + Proof. apply big_opM_ne. Qed. Lemma big_sepM_proper Φ Ψ m : (∀ k x, m !! k = Some x → Φ k x ⊣⊢ Ψ k x) → ([∗ map] k ↦ x ∈ m, Φ k x) ⊣⊢ ([∗ map] k ↦ x ∈ m, Ψ k x). Proof. apply big_opM_proper. Qed. - Lemma big_sepM_subseteq `{BiAffine PROP} Φ m1 m2 : - m2 ⊆ m1 → ([∗ map] k ↦ x ∈ m1, Φ k x) ⊢ [∗ map] k ↦ x ∈ m2, Φ k x. - Proof. rewrite big_opM_eq. intros. by apply big_sepL_submseteq, map_to_list_submseteq. Qed. + (** No need to declare instances for non-expansiveness and properness, we + get both from the generic [big_opM] instances. *) Global Instance big_sepM_mono' : Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢)) (big_opM (@bi_sep PROP) (K:=K) (A:=A)). - Proof. intros f g Hf m ? <-. apply big_sepM_mono=> ???; apply Hf. Qed. + Proof. intros f g Hf m ? <-. apply big_sepM_mono; intros; apply Hf. Qed. Lemma big_sepM_empty Φ : ([∗ map] k↦x ∈ ∅, Φ k x) ⊣⊢ emp. Proof. by rewrite big_opM_empty. Qed. @@ -876,6 +932,8 @@ Section map2. set_unfold=>k. by rewrite !elem_of_dom. Qed. + (** The lemmas [big_sepM2_mono], [big_sepM2_ne] and [big_sepM2_proper] are more + generic than the instances as they also give [mi !! k = Some yi] in the premise. *) Lemma big_sepM2_mono Φ Ψ m1 m2 : (∀ k y1 y2, m1 !! k = Some y1 → m2 !! k = Some y2 → Φ k y1 y2 ⊢ Ψ k y1 y2) → ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2) ⊢ [∗ map] k ↦ y1;y2 ∈ m1;m2, Ψ k y1 y2. @@ -888,6 +946,17 @@ Section map2. destruct (m2 !! k) as [y2|]; simpl; last done. intros ?; simplify_eq. by apply Hm1m2. Qed. + Lemma big_sepM2_ne Φ Ψ m1 m2 n : + (∀ k y1 y2, m1 !! k = Some y1 → m2 !! k = Some y2 → Φ k y1 y2 ≡{n}≡ Ψ k y1 y2) → + ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2)%I ≡{n}≡ ([∗ map] k ↦ y1;y2 ∈ m1;m2, Ψ k y1 y2)%I. + Proof. + intros Hm1m2. rewrite big_sepM2_eq /big_sepM2_def. + f_equiv. apply big_sepM_ne=> k [x1 x2]. rewrite map_lookup_zip_with. + specialize (Hm1m2 k x1 x2). + destruct (m1 !! k) as [y1|]; last done. + destruct (m2 !! k) as [y2|]; simpl; last done. + intros ?; simplify_eq. by apply Hm1m2. + Qed. Lemma big_sepM2_proper Φ Ψ m1 m2 : (∀ k y1 y2, m1 !! k = Some y1 → m2 !! k = Some y2 → Φ k y1 y2 ⊣⊢ Ψ k y1 y2) → ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2) ⊣⊢ [∗ map] k ↦ y1;y2 ∈ m1;m2, Ψ k y1 y2. @@ -895,15 +964,30 @@ Section map2. intros; apply (anti_symm _); apply big_sepM2_mono; auto using equiv_entails, equiv_entails_sym. Qed. - - Global Instance big_sepM2_ne n : + Lemma big_sepM2_proper_2 `{!Equiv A, !Equiv B} Φ Ψ m1 m2 m1' m2' : + m1 ≡ m1' → m2 ≡ m2' → + (∀ k y1 y1' y2 y2', + m1 !! k = Some y1 → m1' !! k = Some y1' → y1 ≡ y1' → + m2 !! k = Some y2 → m2' !! k = Some y2' → y2 ≡ y2' → + Φ k y1 y2 ⊣⊢ Ψ k y1' y2') → + ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2) ⊣⊢ [∗ map] k ↦ y1;y2 ∈ m1';m2', Ψ k y1 y2. + Proof. + intros Hm1 Hm2 Hf. rewrite big_sepM2_eq /big_sepM2_def. f_equiv. + { f_equiv; split; intros Hm k. + - trans (is_Some (m1 !! k)); [symmetry; apply is_Some_proper; by f_equiv|]. + rewrite Hm. apply is_Some_proper; by f_equiv. + - trans (is_Some (m1' !! k)); [apply is_Some_proper; by f_equiv|]. + rewrite Hm. symmetry. apply is_Some_proper; by f_equiv. } + apply big_opM_proper_2; [by f_equiv|]. + intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some + (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some [??]; naive_solver. + Qed. + + Global Instance big_sepM2_ne' n : Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (dist n))) ==> (=) ==> (=) ==> (dist n)) (big_sepM2 (PROP:=PROP) (K:=K) (A:=A) (B:=B)). - Proof. - intros Φ1 Φ2 HΦ x1 ? <- x2 ? <-. rewrite big_sepM2_eq /big_sepM2_def. - f_equiv. f_equiv=> k [y1 y2]. apply HΦ. - Qed. + Proof. intros f g Hf m1 ? <- m2 ? <-. apply big_sepM2_ne; intros; apply Hf. Qed. Global Instance big_sepM2_mono' : Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (⊢))) ==> (=) ==> (=) ==> (⊢)) (big_sepM2 (PROP:=PROP) (K:=K) (A:=A) (B:=B)). @@ -1182,18 +1266,27 @@ Section gset. Implicit Types X : gset A. Implicit Types Φ : A → PROP. + Lemma big_sepS_subseteq `{BiAffine PROP} Φ X Y : + Y ⊆ X → ([∗ set] x ∈ X, Φ x) ⊢ [∗ set] x ∈ Y, Φ x. + Proof. rewrite big_opS_eq. intros. by apply big_sepL_submseteq, elements_submseteq. Qed. + + (** The lemmas [big_sepS_mono], [big_sepS_ne] and [big_sepS_proper] are more + generic than the instances as they also give [x ∈ X] in the premise. *) Lemma big_sepS_mono Φ Ψ X : (∀ x, x ∈ X → Φ x ⊢ Ψ x) → ([∗ set] x ∈ X, Φ x) ⊢ [∗ set] x ∈ X, Ψ x. - Proof. intros. apply big_opS_forall; apply _ || auto. Qed. + Proof. intros. apply big_opS_gen_proper; apply _ || auto. Qed. + Lemma big_sepS_ne Φ Ψ X n : + (∀ x, x ∈ X → Φ x ≡{n}≡ Ψ x) → + ([∗ set] x ∈ X, Φ x)%I ≡{n}≡ ([∗ set] x ∈ X, Ψ x)%I. + Proof. apply big_opS_ne. Qed. Lemma big_sepS_proper Φ Ψ X : (∀ x, x ∈ X → Φ x ⊣⊢ Ψ x) → ([∗ set] x ∈ X, Φ x) ⊣⊢ ([∗ set] x ∈ X, Ψ x). Proof. apply big_opS_proper. Qed. - Lemma big_sepS_subseteq `{BiAffine PROP} Φ X Y : - Y ⊆ X → ([∗ set] x ∈ X, Φ x) ⊢ [∗ set] x ∈ Y, Φ x. - Proof. rewrite big_opS_eq. intros. by apply big_sepL_submseteq, elements_submseteq. Qed. + (** No need to declare instances for non-expansiveness and properness, we + get both from the generic [big_opS] instances. *) Global Instance big_sepS_mono' : Proper (pointwise_relation _ (⊢) ==> (=) ==> (⊢)) (big_opS (@bi_sep PROP) (A:=A)). Proof. intros f g Hf m ? <-. by apply big_sepS_mono. Qed. @@ -1344,18 +1437,27 @@ Section gmultiset. Implicit Types X : gmultiset A. Implicit Types Φ : A → PROP. + Lemma big_sepMS_subseteq `{BiAffine PROP} Φ X Y : + Y ⊆ X → ([∗ mset] x ∈ X, Φ x) ⊢ [∗ mset] x ∈ Y, Φ x. + Proof. rewrite big_opMS_eq. intros. by apply big_sepL_submseteq, gmultiset_elements_submseteq. Qed. + + (** The lemmas [big_sepMS_mono], [big_sepMS_ne] and [big_sepMS_proper] are more + generic than the instances as they also give [l !! k = Some y] in the premise. *) Lemma big_sepMS_mono Φ Ψ X : (∀ x, x ∈ X → Φ x ⊢ Ψ x) → ([∗ mset] x ∈ X, Φ x) ⊢ [∗ mset] x ∈ X, Ψ x. - Proof. intros. apply big_opMS_forall; apply _ || auto. Qed. + Proof. intros. apply big_opMS_gen_proper; apply _ || auto. Qed. + Lemma big_sepMS_ne Φ Ψ X n : + (∀ x, x ∈ X → Φ x ≡{n}≡ Ψ x) → + ([∗ mset] x ∈ X, Φ x)%I ≡{n}≡ ([∗ mset] x ∈ X, Ψ x)%I. + Proof. apply big_opMS_ne. Qed. Lemma big_sepMS_proper Φ Ψ X : (∀ x, x ∈ X → Φ x ⊣⊢ Ψ x) → ([∗ mset] x ∈ X, Φ x) ⊣⊢ ([∗ mset] x ∈ X, Ψ x). Proof. apply big_opMS_proper. Qed. - Lemma big_sepMS_subseteq `{BiAffine PROP} Φ X Y : - Y ⊆ X → ([∗ mset] x ∈ X, Φ x) ⊢ [∗ mset] x ∈ Y, Φ x. - Proof. rewrite big_opMS_eq. intros. by apply big_sepL_submseteq, gmultiset_elements_submseteq. Qed. + (** No need to declare instances for non-expansiveness and properness, we + get both from the generic [big_opMS] instances. *) Global Instance big_sepMS_mono' : Proper (pointwise_relation _ (⊢) ==> (=) ==> (⊢)) (big_opMS (@bi_sep PROP) (A:=A)). Proof. intros f g Hf m ? <-. by apply big_sepMS_mono. Qed.