Commit ebcb867c by Robbert Krebbers Committed by Ralf Jung

### Initial Iris commit

parent 02f213ce
 ... ... @@ -23,6 +23,7 @@ Arguments compose _ _ _ _ _ _ /. Arguments flip _ _ _ _ _ _ /. Arguments const _ _ _ _ /. Typeclasses Transparent id compose flip const. Instance: Params (@pair) 2. (** Change [True] and [False] into notations in order to enable overloading. We will use this in the file [assertions] to give [True] and [False] a ... ... @@ -792,6 +793,11 @@ Instance pointwise_transitive {A} `{R : relation B} : Transitive R → Transitive (pointwise_relation A R) | 9. Proof. firstorder. Qed. (** ** Unit *) Instance unit_equiv : Equiv unit := λ _ _, True. Instance unit_equivalence : Equivalence (@equiv unit _). Proof. repeat split. Qed. (** ** Products *) Instance prod_map_injective {A A' B B'} (f : A → A') (g : B → B') : Injective (=) (=) f → Injective (=) (=) g → ... ... @@ -825,6 +831,15 @@ Section prod_relation. Proof. firstorder eauto. Qed. End prod_relation. Instance prod_equiv `{Equiv A,Equiv B} : Equiv (A * B) := prod_relation (≡) (≡). Instance pair_proper `{Equiv A, Equiv B} : Proper ((≡) ==> (≡) ==> (≡)) (@pair A B) | 0 := _. Instance fst_proper `{Equiv A, Equiv B} : Proper ((≡) ==> (≡)) (@fst A B) | 0 := _. Instance snd_proper `{Equiv A, Equiv B} : Proper ((≡) ==> (≡)) (@snd A B) | 0 := _. Typeclasses Opaque prod_equiv. (** ** Other *) Lemma or_l P Q : ¬Q → P ∨ Q ↔ P. Proof. tauto. Qed. ... ...
 ... ... @@ -249,7 +249,7 @@ Ltac unfold_elem_of := For goals that do not involve [≡], [⊆], [map], or quantifiers this tactic is generally powerful enough. This tactic either fails or proves the goal. *) Tactic Notation "solve_elem_of" tactic3(tac) := simpl in *; setoid_subst; decompose_empty; unfold_elem_of; solve [intuition (simplify_equality; tac)]. ... ... @@ -261,7 +261,7 @@ fails or loops on very small goals generated by [solve_elem_of] already. We use the [naive_solver] tactic as a substitute. This tactic either fails or proves the goal. *) Tactic Notation "esolve_elem_of" tactic3(tac) := simpl in *; setoid_subst; decompose_empty; unfold_elem_of; naive_solver tac. ... ... @@ -273,6 +273,11 @@ Section collection. Global Instance: Lattice C. Proof. split. apply _. firstorder auto. solve_elem_of. Qed. Global Instance difference_proper : Proper ((≡) ==> (≡) ==> (≡)) (∖). Proof. intros X1 X2 HX Y1 Y2 HY; apply elem_of_equiv; intros x. by rewrite !elem_of_difference, HX, HY. Qed. Lemma intersection_singletons x : {[x]} ∩ {[x]} ≡ {[x]}. Proof. esolve_elem_of. Qed. Lemma difference_twice X Y : (X ∖ Y) ∖ Y ≡ X ∖ Y. ... ... @@ -283,6 +288,8 @@ Section collection. Proof. esolve_elem_of. Qed. Lemma difference_union_distr_l X Y Z : (X ∪ Y) ∖ Z ≡ X ∖ Z ∪ Y ∖ Z. Proof. esolve_elem_of. Qed. Lemma difference_union_distr_r X Y Z : Z ∖ (X ∪ Y) ≡ (Z ∖ X) ∩ (Z ∖ Y). Proof. esolve_elem_of. Qed. Lemma difference_intersection_distr_l X Y Z : (X ∩ Y) ∖ Z ≡ X ∖ Z ∩ Y ∖ Z. Proof. esolve_elem_of. Qed. ... ... @@ -298,6 +305,8 @@ Section collection. Proof. unfold_leibniz. apply difference_diag. Qed. Lemma difference_union_distr_l_L X Y Z : (X ∪ Y) ∖ Z = X ∖ Z ∪ Y ∖ Z. Proof. unfold_leibniz. apply difference_union_distr_l. Qed. Lemma difference_union_distr_r_L X Y Z : Z ∖ (X ∪ Y) = (Z ∖ X) ∩ (Z ∖ Y). Proof. unfold_leibniz. apply difference_union_distr_r. Qed. Lemma difference_intersection_distr_l_L X Y Z : (X ∩ Y) ∖ Z = X ∖ Z ∩ Y ∖ Z. Proof. unfold_leibniz. apply difference_intersection_distr_l. Qed. ... ... @@ -518,16 +527,13 @@ Section collection_monad. Global Instance collection_fmap_proper {A B} (f : A → B) : Proper ((≡) ==> (≡)) (fmap f). Proof. intros X Y E. esolve_elem_of. Qed. Global Instance collection_ret_proper {A} : Proper ((=) ==> (≡)) (@mret M _ A). Proof. intros X Y E. esolve_elem_of. Qed. Proof. intros X Y [??]; split; esolve_elem_of. Qed. Global Instance collection_bind_proper {A B} (f : A → M B) : Proper ((≡) ==> (≡)) (mbind f). Proof. intros X Y E. esolve_elem_of. Qed. Proof. intros X Y [??]; split; esolve_elem_of. Qed. Global Instance collection_join_proper {A} : Proper ((≡) ==> (≡)) (@mjoin M _ A). Proof. intros X Y E. esolve_elem_of. Qed. Proof. intros X Y [??]; split; esolve_elem_of. Qed. Lemma collection_bind_singleton {A B} (f : A → M B) x : {[ x ]} ≫= f ≡ f x. Proof. esolve_elem_of. Qed. ... ...
 ... ... @@ -3,7 +3,7 @@ (** This file collects definitions and theorems on finite collections. Most importantly, it implements a fold and size function and some useful induction principles on finite collections . *) Require Import Permutation ars listset. Require Import Permutation relations listset. Require Export numbers collections. Instance collection_size `{Elements A C} : Size C := length ∘ elements. ... ...
 ... ... @@ -77,15 +77,15 @@ Proof. rewrite not_elem_of_dom. apply delete_partial_alter. Qed. Lemma delete_insert_dom {A} (m : M A) i x : i ∉ dom D m → delete i (<[i:=x]>m) = m. Proof. rewrite not_elem_of_dom. apply delete_insert. Qed. Lemma map_disjoint_dom {A} (m1 m2 : M A) : m1 ⊥ m2 ↔ dom D m1 ∩ dom D m2 ≡ ∅. Lemma map_disjoint_dom {A} (m1 m2 : M A) : m1 ⊥ₘ m2 ↔ dom D m1 ∩ dom D m2 ≡ ∅. Proof. rewrite map_disjoint_spec, elem_of_equiv_empty. setoid_rewrite elem_of_intersection. setoid_rewrite elem_of_dom. unfold is_Some. naive_solver. Qed. Lemma map_disjoint_dom_1 {A} (m1 m2 : M A) : m1 ⊥ m2 → dom D m1 ∩ dom D m2 ≡ ∅. Lemma map_disjoint_dom_1 {A} (m1 m2 : M A) : m1 ⊥ₘ m2 → dom D m1 ∩ dom D m2 ≡ ∅. Proof. apply map_disjoint_dom. Qed. Lemma map_disjoint_dom_2 {A} (m1 m2 : M A) : dom D m1 ∩ dom D m2 ≡ ∅ → m1 ⊥ m2. Lemma map_disjoint_dom_2 {A} (m1 m2 : M A) : dom D m1 ∩ dom D m2 ≡ ∅ → m1 ⊥ₘ m2. Proof. apply map_disjoint_dom. Qed. Lemma dom_union {A} (m1 m2 : M A) : dom D (m1 ∪ m2) ≡ dom D m1 ∪ dom D m2. Proof. ... ...
 ... ... @@ -5,7 +5,7 @@ finite maps and collects some theory on it. Most importantly, it proves useful induction principles for finite maps and implements the tactic [simplify_map_equality] to simplify goals involving finite maps. *) Require Import Permutation. Require Export ars vector orders. Require Export relations vector orders. (** * Axiomatization of finite maps *) (** We require Leibniz equality to be extensional on finite maps. This of ... ... @@ -71,25 +71,26 @@ Instance map_intersection_with `{Merge M} {A} : IntersectionWith A (M A) := Instance map_difference_with `{Merge M} {A} : DifferenceWith A (M A) := λ f, merge (difference_with f). Instance map_equiv `{∀ A, Lookup K A (M A), Equiv A} : Equiv (M A) | 1 := λ m1 m2, ∀ i, m1 !! i ≡ m2 !! i. (** The relation [intersection_forall R] on finite maps describes that the relation [R] holds for each pair in the intersection. *) Definition map_Forall `{Lookup K A M} (P : K → A → Prop) : M → Prop := λ m, ∀ i x, m !! i = Some x → P i x. Definition map_Forall2 `{∀ A, Lookup K A (M A)} {A B} (R : A → B → Prop) (P : A → Prop) (Q : B → Prop) (m1 : M A) (m2 : M B) : Prop := ∀ i, match m1 !! i, m2 !! i with | Some x, Some y => R x y | Some x, None => P x | None, Some y => Q y | None, None => True end. Definition map_relation `{∀ A, Lookup K A (M A)} {A B} (R : A → B → Prop) (P : A → Prop) (Q : B → Prop) (m1 : M A) (m2 : M B) : Prop := ∀ i, option_relation R P Q (m1 !! i) (m2 !! i). Definition map_included `{∀ A, Lookup K A (M A)} {A} (R : relation A) : relation (M A) := map_Forall2 R (λ _, False) (λ _, True). Instance map_disjoint `{∀ A, Lookup K A (M A)} {A} : Disjoint (M A) := map_Forall2 (λ _ _, False) (λ _, True) (λ _, True). (R : relation A) : relation (M A) := map_relation R (λ _, False) (λ _, True). Definition map_disjoint `{∀ A, Lookup K A (M A)} {A} : relation (M A) := map_relation (λ _ _, False) (λ _, True) (λ _, True). Infix "⊥ₘ" := map_disjoint (at level 70) : C_scope. Hint Extern 0 (_ ⊥ₘ _) => symmetry; eassumption. Notation "( m ⊥ₘ.)" := (map_disjoint m) (only parsing) : C_scope. Notation "(.⊥ₘ m )" := (λ m2, m2 ⊥ₘ m) (only parsing) : C_scope. Instance map_subseteq `{∀ A, Lookup K A (M A)} {A} : SubsetEq (M A) := map_Forall2 (=) (λ _, False) (λ _, True). map_included (=). (** The union of two finite maps only has a meaningful definition for maps that are disjoint. However, as working with partial functions is inconvenient ... ... @@ -114,12 +115,67 @@ Definition map_imap `{∀ A, Insert K A (M A), ∀ A, Empty (M A), Section theorems. Context `{FinMap K M}. (** ** Setoids *) Section setoid. Context `{Equiv A}. Global Instance map_equivalence `{!Equivalence ((≡) : relation A)} : Equivalence ((≡) : relation (M A)). Proof. split. * by intros m i. * by intros m1 m2 ? i. * by intros m1 m2 m3 ?? i; transitivity (m2 !! i). Qed. Global Instance lookup_proper (i : K) : Proper ((≡) ==> (≡)) (lookup (M:=M A) i). Proof. by intros m1 m2 Hm. Qed. Global Instance partial_alter_proper : Proper (((≡) ==> (≡)) ==> (=) ==> (≡) ==> (≡)) partial_alter. Proof. by intros f1 f2 Hf i ? <- m1 m2 Hm j; destruct (decide (i = j)) as [->|]; rewrite ?lookup_partial_alter, ?lookup_partial_alter_ne by done; try apply Hf; apply lookup_proper. Qed. Global Instance insert_proper (i : K) : Proper ((≡) ==> (≡) ==> (≡)) (insert (M:=M A) i). Proof. by intros ???; apply partial_alter_proper; [constructor|]. Qed. Global Instance delete_proper (i : K) : Proper ((≡) ==> (≡)) (delete (M:=M A) i). Proof. by apply partial_alter_proper; [constructor|]. Qed. Global Instance alter_proper : Proper (((≡) ==> (≡)) ==> (=) ==> (≡) ==> (≡)) (alter (A:=A) (M:=M A)). Proof. intros ?? Hf; apply partial_alter_proper. by destruct 1; constructor; apply Hf. Qed. Lemma merge_ext f g `{!PropHolds (f None None = None), !PropHolds (g None None = None)} : ((≡) ==> (≡) ==> (≡))%signature f g → ((≡) ==> (≡) ==> (≡))%signature (merge f) (merge g). Proof. by intros Hf ?? Hm1 ?? Hm2 i; rewrite !lookup_merge by done; apply Hf. Qed. Global Instance union_with_proper : Proper (((≡) ==> (≡) ==> (≡)) ==> (≡) ==> (≡) ==> (≡)) union_with. Proof. intros ?? Hf ?? Hm1 ?? Hm2 i; apply (merge_ext _ _); auto. by do 2 destruct 1; first [apply Hf | constructor]. Qed. Global Instance map_leibniz `{!LeibnizEquiv A} : LeibnizEquiv (M A). Proof. intros m1 m2; split. * by intros Hm; apply map_eq; intros i; unfold_leibniz; apply lookup_proper. * by intros <-; intros i; fold_leibniz. Qed. End setoid. (** ** General properties *) Lemma map_eq_iff {A} (m1 m2 : M A) : m1 = m2 ↔ ∀ i, m1 !! i = m2 !! i. Proof. split. by intros ->. apply map_eq. Qed. Lemma map_subseteq_spec {A} (m1 m2 : M A) : m1 ⊆ m2 ↔ ∀ i x, m1 !! i = Some x → m2 !! i = Some x. Proof. unfold subseteq, map_subseteq, map_Forall2. split; intros Hm i; unfold subseteq, map_subseteq, map_relation. split; intros Hm i; specialize (Hm i); destruct (m1 !! i), (m2 !! i); naive_solver. Qed. Global Instance: EmptySpec (M A). ... ... @@ -129,9 +185,10 @@ Proof. Qed. Global Instance: ∀ {A} (R : relation A), PreOrder R → PreOrder (map_included R). Proof. split; [intros m i; by destruct (m !! i)|]. split; [intros m i; by destruct (m !! i); simpl|]. intros m1 m2 m3 Hm12 Hm23 i; specialize (Hm12 i); specialize (Hm23 i). destruct (m1 !! i), (m2 !! i), (m3 !! i); try done; etransitivity; eauto. destruct (m1 !! i), (m2 !! i), (m3 !! i); simplify_equality'; done || etransitivity; eauto. Qed. Global Instance: PartialOrder ((⊆) : relation (M A)). Proof. ... ... @@ -357,8 +414,8 @@ Lemma insert_included {A} R `{!Reflexive R} (m : M A) i x : (∀ y, m !! i = Some y → R y x) → map_included R m (<[i:=x]>m). Proof. intros ? j; destruct (decide (i = j)) as [->|]. * rewrite lookup_insert. destruct (m !! j); eauto. * rewrite lookup_insert_ne by done. by destruct (m !! j). * rewrite lookup_insert. destruct (m !! j); simpl; eauto. * rewrite lookup_insert_ne by done. by destruct (m !! j); simpl. Qed. Lemma insert_subseteq {A} (m : M A) i x : m !! i = None → m ⊆ <[i:=x]>m. Proof. apply partial_alter_subseteq. Qed. ... ... @@ -465,6 +522,17 @@ Proof. * by rewrite lookup_omap, !lookup_singleton. * by rewrite lookup_omap, !lookup_singleton_ne. Qed. Lemma map_fmap_id {A} (m : M A) : id <\$> m = m. Proof. apply map_eq; intros i; by rewrite lookup_fmap, option_fmap_id. Qed. Lemma map_fmap_compose {A B C} (f : A → B) (g : B → C) (m : M A) : g ∘ f <\$> m = g <\$> f <\$> m. Proof. apply map_eq; intros i; by rewrite !lookup_fmap,option_fmap_compose. Qed. Lemma map_fmap_ext {A B} (f1 f2 : A → B) m : (∀ i x, m !! i = Some x → f1 x = f2 x) → f1 <\$> m = f2 <\$> m. Proof. intros Hi; apply map_eq; intros i; rewrite !lookup_fmap. by destruct (m !! i) eqn:?; simpl; erewrite ?Hi by eauto. Qed. (** ** Properties of conversion to lists *) Lemma map_to_list_unique {A} (m : M A) i x y : ... ... @@ -807,7 +875,7 @@ Lemma insert_merge_r m1 m2 i x z : Proof. by intros; apply partial_alter_merge_r. Qed. End more_merge. (** ** Properties on the [map_Forall2] relation *) (** ** Properties on the [map_relation] relation *) Section Forall2. Context {A B} (R : A → B → Prop) (P : A → Prop) (Q : B → Prop). Context `{∀ x y, Decision (R x y), ∀ x, Decision (P x), ∀ y, Decision (Q y)}. ... ... @@ -819,8 +887,8 @@ Let f (mx : option A) (my : option B) : option bool := | None, Some y => Some (bool_decide (Q y)) | None, None => None end. Lemma map_Forall2_alt (m1 : M A) (m2 : M B) : map_Forall2 R P Q m1 m2 ↔ map_Forall (λ _, Is_true) (merge f m1 m2). Lemma map_relation_alt (m1 : M A) (m2 : M B) : map_relation R P Q m1 m2 ↔ map_Forall (λ _, Is_true) (merge f m1 m2). Proof. split. * intros Hm i P'; rewrite lookup_merge by done; intros. ... ... @@ -830,71 +898,72 @@ Proof. destruct (m1 !! i), (m2 !! i); simplify_equality'; auto; by eapply bool_decide_unpack, Hm. Qed. Global Instance map_Forall2_dec `{∀ x y, Decision (R x y), ∀ x, Decision (P x), ∀ y, Decision (Q y)} m1 m2 : Decision (map_Forall2 R P Q m1 m2). Global Instance map_relation_dec `{∀ x y, Decision (R x y), ∀ x, Decision (P x), ∀ y, Decision (Q y)} m1 m2 : Decision (map_relation R P Q m1 m2). Proof. refine (cast_if (decide (map_Forall (λ _, Is_true) (merge f m1 m2)))); abstract by rewrite map_Forall2_alt. abstract by rewrite map_relation_alt. Defined. (** Due to the finiteness of finite maps, we can extract a witness if the relation does not hold. *) Lemma map_not_Forall2 (m1 : M A) (m2 : M B) : ¬map_Forall2 R P Q m1 m2 ↔ ∃ i, ¬map_relation R P Q m1 m2 ↔ ∃ i, (∃ x y, m1 !! i = Some x ∧ m2 !! i = Some y ∧ ¬R x y) ∨ (∃ x, m1 !! i = Some x ∧ m2 !! i = None ∧ ¬P x) ∨ (∃ y, m1 !! i = None ∧ m2 !! i = Some y ∧ ¬Q y). Proof. split. * rewrite map_Forall2_alt, (map_not_Forall _). intros (i&?&Hm&?); exists i. * rewrite map_relation_alt, (map_not_Forall _). intros (i&?&Hm&?); exists i. rewrite lookup_merge in Hm by done. destruct (m1 !! i), (m2 !! i); naive_solver auto 2 using bool_decide_pack. * by intros [i[(x&y&?&?&?)|[(x&?&?&?)|(y&?&?&?)]]] Hm; * unfold map_relation, option_relation. by intros [i[(x&y&?&?&?)|[(x&?&?&?)|(y&?&?&?)]]] Hm; specialize (Hm i); simplify_option_equality. Qed. End Forall2. (** ** Properties on the disjoint maps *) Lemma map_disjoint_spec {A} (m1 m2 : M A) : m1 ⊥ m2 ↔ ∀ i x y, m1 !! i = Some x → m2 !! i = Some y → False. m1 ⊥ₘ m2 ↔ ∀ i x y, m1 !! i = Some x → m2 !! i = Some y → False. Proof. split; intros Hm i; specialize (Hm i); destruct (m1 !! i), (m2 !! i); naive_solver. Qed. Lemma map_disjoint_alt {A} (m1 m2 : M A) : m1 ⊥ m2 ↔ ∀ i, m1 !! i = None ∨ m2 !! i = None. m1 ⊥ₘ m2 ↔ ∀ i, m1 !! i = None ∨ m2 !! i = None. Proof. split; intros Hm1m2 i; specialize (Hm1m2 i); destruct (m1 !! i), (m2 !! i); naive_solver. Qed. Lemma map_not_disjoint {A} (m1 m2 : M A) : ¬m1 ⊥ m2 ↔ ∃ i x1 x2, m1 !! i = Some x1 ∧ m2 !! i = Some x2. ¬m1 ⊥ₘ m2 ↔ ∃ i x1 x2, m1 !! i = Some x1 ∧ m2 !! i = Some x2. Proof. unfold disjoint, map_disjoint. rewrite map_not_Forall2 by solve_decision. split; [|naive_solver]. intros [i[(x&y&?&?&?)|[(x&?&?&[])|(y&?&?&[])]]]; naive_solver. Qed. Global Instance: Symmetric (@disjoint (M A) _). Global Instance: Symmetric (map_disjoint : relation (M A)). Proof. intros A m1 m2. rewrite !map_disjoint_spec. naive_solver. Qed. Lemma map_disjoint_empty_l {A} (m : M A) : ∅ ⊥ m. Lemma map_disjoint_empty_l {A} (m : M A) : ∅ ⊥ₘ m. Proof. rewrite !map_disjoint_spec. intros i x y. by rewrite lookup_empty. Qed. Lemma map_disjoint_empty_r {A} (m : M A) : m ⊥ ∅. Lemma map_disjoint_empty_r {A} (m : M A) : m ⊥ₘ ∅. Proof. rewrite !map_disjoint_spec. intros i x y. by rewrite lookup_empty. Qed. Lemma map_disjoint_weaken {A} (m1 m1' m2 m2' : M A) : m1' ⊥ m2' → m1 ⊆ m1' → m2 ⊆ m2' → m1 ⊥ m2. m1' ⊥ₘ m2' → m1 ⊆ m1' → m2 ⊆ m2' → m1 ⊥ₘ m2. Proof. rewrite !map_subseteq_spec, !map_disjoint_spec. eauto. Qed. Lemma map_disjoint_weaken_l {A} (m1 m1' m2 : M A) : m1' ⊥ m2 → m1 ⊆ m1' → m1 ⊥ m2. m1' ⊥ₘ m2 → m1 ⊆ m1' → m1 ⊥ₘ m2. Proof. eauto using map_disjoint_weaken. Qed. Lemma map_disjoint_weaken_r {A} (m1 m2 m2' : M A) : m1 ⊥ m2' → m2 ⊆ m2' → m1 ⊥ m2. m1 ⊥ₘ m2' → m2 ⊆ m2' → m1 ⊥ₘ m2. Proof. eauto using map_disjoint_weaken. Qed. Lemma map_disjoint_Some_l {A} (m1 m2 : M A) i x: m1 ⊥ m2 → m1 !! i = Some x → m2 !! i = None. m1 ⊥ₘ m2 → m1 !! i = Some x → m2 !! i = None. Proof. rewrite map_disjoint_spec, eq_None_not_Some. intros ?? [??]; eauto. Qed. Lemma map_disjoint_Some_r {A} (m1 m2 : M A) i x: m1 ⊥ m2 → m2 !! i = Some x → m1 !! i = None. Proof. rewrite (symmetry_iff (⊥)). apply map_disjoint_Some_l. Qed. Lemma map_disjoint_singleton_l {A} (m : M A) i x : {[i, x]} ⊥ m ↔ m !! i = None. m1 ⊥ₘ m2 → m2 !! i = Some x → m1 !! i = None. Proof. rewrite (symmetry_iff map_disjoint). apply map_disjoint_Some_l. Qed. Lemma map_disjoint_singleton_l {A} (m: M A) i x : {[i, x]} ⊥ₘ m ↔ m !! i = None. Proof. split; [|rewrite !map_disjoint_spec]. * intro. apply (map_disjoint_Some_l {[i, x]} _ _ x); ... ... @@ -904,20 +973,20 @@ Proof. + by rewrite lookup_singleton_ne. Qed. Lemma map_disjoint_singleton_r {A} (m : M A) i x : m ⊥ {[i, x]} ↔ m !! i = None. Proof. by rewrite (symmetry_iff (⊥)), map_disjoint_singleton_l. Qed. m ⊥ₘ {[i, x]} ↔ m !! i = None. Proof. by rewrite (symmetry_iff map_disjoint), map_disjoint_singleton_l. Qed. Lemma map_disjoint_singleton_l_2 {A} (m : M A) i x : m !! i = None → {[i, x]} ⊥ m. m !! i = None → {[i, x]} ⊥ₘ m. Proof. by rewrite map_disjoint_singleton_l. Qed. Lemma map_disjoint_singleton_r_2 {A} (m : M A) i x : m !! i = None → m ⊥ {[i, x]}. m !! i = None → m ⊥ₘ {[i, x]}. Proof. by rewrite map_disjoint_singleton_r. Qed. Lemma map_disjoint_delete_l {A} (m1 m2 : M A) i : m1 ⊥ m2 → delete i m1 ⊥ m2. Lemma map_disjoint_delete_l {A} (m1 m2 : M A) i : m1 ⊥ₘ m2 → delete i m1 ⊥ₘ m2. Proof. rewrite !map_disjoint_alt. intros Hdisjoint j. destruct (Hdisjoint j); auto. rewrite lookup_delete_None. tauto. Qed. Lemma map_disjoint_delete_r {A} (m1 m2 : M A) i : m1 ⊥ m2 → m1 ⊥ delete i m2. Lemma map_disjoint_delete_r {A} (m1 m2 : M A) i : m1 ⊥ₘ m2 → m1 ⊥ₘ delete i m2. Proof. symmetry. by apply map_disjoint_delete_l. Qed. (** ** Properties of the [union_with] operation *) ... ... @@ -1036,7 +1105,7 @@ Qed. Lemma map_positive_l_alt {A} (m1 m2 : M A) : m1 ≠ ∅ → m1 ∪ m2 ≠ ∅. Proof. eauto using map_positive_l. Qed. Lemma lookup_union_Some {A} (m1 m2 : M A) i x : m1 ⊥ m2 → (m1 ∪ m2) !! i = Some x ↔ m1 !! i = Some x ∨ m2 !! i = Some x. m1 ⊥ₘ m2 → (m1 ∪ m2) !! i = Some x ↔ m1 !! i = Some x ∨ m2 !! i = Some x. Proof. intros Hdisjoint. rewrite lookup_union_Some_raw. intuition eauto using map_disjoint_Some_r. ... ... @@ -1045,9 +1114,9 @@ Lemma lookup_union_Some_l {A} (m1 m2 : M A) i x : m1 !! i = Some x → (m1 ∪ m2) !! i = Some x. Proof. intro. rewrite lookup_union_Some_raw; intuition. Qed. Lemma lookup_union_Some_r {A} (m1 m2 : M A) i x : m1 ⊥ m2 → m2 !! i = Some x → (m1 ∪ m2) !! i = Some x. m1 ⊥ₘ m2 → m2 !! i = Some x → (m1 ∪ m2) !! i = Some x. Proof. intro. rewrite lookup_union_Some; intuition. Qed. Lemma map_union_commutative {A} (m1 m2 : M A) : m1 ⊥ m2 → m1 ∪ m2 = m2 ∪ m1. Lemma map_union_commutative {A} (m1 m2 : M A) : m1 ⊥ₘ m2 → m1 ∪ m2 = m2 ∪ m1. Proof. intros Hdisjoint. apply (merge_commutative (union_with (λ x _, Some x))). intros i. specialize (Hdisjoint i). ... ... @@ -1065,14 +1134,14 @@ Lemma map_union_subseteq_l {A} (m1 m2 : M A) : m1 ⊆ m1 ∪ m2. Proof. rewrite map_subseteq_spec. intros ? i x. rewrite lookup_union_Some_raw. tauto. Qed. Lemma map_union_subseteq_r {A} (m1 m2 : M A) : m1 ⊥ m2 → m2 ⊆ m1 ∪ m2. Lemma map_union_subseteq_r {A} (m1 m2 : M A) : m1 ⊥ₘ m2 → m2 ⊆ m1 ∪ m2. Proof. intros. rewrite map_union_commutative by done. by apply map_union_subseteq_l. Qed. Lemma map_union_subseteq_l_alt {A} (m1 m2 m3 : M A) : m1 ⊆ m2 → m1 ⊆ m2 ∪ m3. Proof. intros. transitivity m2; auto using map_union_subseteq_l. Qed. Lemma map_union_subseteq_r_alt {A} (m1 m2 m3 : M A) : m2 ⊥ m3 → m1 ⊆ m3 → m1 ⊆ m2 ∪ m3. m2 ⊥ₘ m3 → m1 ⊆ m3 → m1 ⊆ m2 ∪ m3. Proof. intros. transitivity m3; auto using map_union_subseteq_r. Qed. Lemma map_union_preserving_l {A} (m1 m2 m3 : M A) : m1 ⊆ m2 → m3 ∪ m1 ⊆ m3 ∪ m2. Proof. ... ... @@ -1080,52 +1149,52 @@ Proof. rewrite !lookup_union_Some_raw. naive_solver. Qed. Lemma map_union_preserving_r {A} (m1 m2 m3 : M A) : m2 ⊥ m3 → m1 ⊆ m2 → m1 ∪ m3 ⊆ m2 ∪ m3. m2 ⊥ₘ m3 → m1 ⊆ m2 → m1 ∪ m3 ⊆ m2 ∪ m3. Proof. intros. rewrite !(map_union_commutative _ m3) by eauto using map_disjoint_weaken_l. by apply map_union_preserving_l. Qed. Lemma map_union_reflecting_l {A} (m1 m2 m3 : M A) : m3 ⊥ m1 → m3 ⊥ m2 → m3 ∪ m1 ⊆ m3 ∪ m2 → m1 ⊆ m2. m3 ⊥ₘ m1 → m3 ⊥ₘ m2 → m3 ∪ m1 ⊆ m3 ∪ m2 → m1 ⊆ m2. Proof. rewrite !map_subseteq_spec. intros Hm31 Hm32 Hm i x ?. specialize (Hm i x). rewrite !lookup_union_Some in Hm by done. destruct Hm; auto. by rewrite map_disjoint_spec in Hm31; destruct (Hm31 i x x). Qed. Lemma map_union_reflecting_r {A} (m1 m2 m3 : M A) : m1 ⊥ m3 → m2 ⊥ m3 → m1 ∪ m3 ⊆ m2 ∪ m3 → m1 ⊆ m2. m1 ⊥ₘ m3 → m2 ⊥ₘ m3 → m1 ∪ m3 ⊆ m2 ∪ m3 → m1 ⊆ m2. Proof. intros ??. rewrite !(map_union_commutative _ m3) by done. by apply map_union_reflecting_l. Qed. Lemma map_union_cancel_l {A} (m1 m2 m3 : M A) : m1 ⊥ m3 → m2 ⊥ m3 → m3 ∪ m1 = m3 ∪ m2 → m1 = m2. m1 ⊥ₘ m3 → m2 ⊥ₘ m3 → m3 ∪ m1 = m3 ∪ m2 → m1 = m2. Proof. intros. apply (anti_symmetric (⊆)); apply map_union_reflecting_l with m3; auto using (reflexive_eq (R:=(⊆))). Qed. Lemma map_union_cancel_r {A} (m1 m2 m3 : M A) : m1 ⊥ m3 → m2 ⊥ m3 → m1 ∪ m3 = m2 ∪ m3 → m1 = m2. m1 ⊥ₘ m3 → m2 ⊥ₘ m3 → m1 ∪ m3 = m2 ∪ m3 → m1 = m2. Proof. intros. apply (anti_symmetric (⊆)); apply map_union_reflecting_r with m3; auto using (reflexive_eq (R:=(⊆))). Qed. Lemma map_disjoint_union_l {A} (m1 m2 m3 : M A) : m1 ∪ m2 ⊥ m3 ↔ m1 ⊥ m3 ∧ m2 ⊥ m3. m1 ∪ m2 ⊥ₘ m3 ↔ m1 ⊥ₘ m3 ∧ m2 ⊥ₘ m3. Proof. rewrite !map_disjoint_alt. setoid_rewrite lookup_union_None. naive_solver. Qed. Lemma map_disjoint_union_r {A} (m1 m2 m3 : M A) : m1 ⊥ m2 ∪ m3 ↔ m1 ⊥ m2 ∧ m1 ⊥ m3. m1 ⊥ₘ m2 ∪ m3 ↔ m1 ⊥ₘ m2 ∧ m1 ⊥ₘ m3.