From a90a8e99a1ce7b4dbc4ea68cb389a1d8fbb896f2 Mon Sep 17 00:00:00 2001 From: Robbert Krebbers <mail@robbertkrebbers.nl> Date: Sat, 23 Jul 2016 01:26:35 +0200 Subject: [PATCH] CMRA structure on gsets that avoids the indirection via maps. Also, add algebra/gset to _CoqProject. --- _CoqProject | 1 + algebra/gset.v | 117 +++++++++++++++++++++++++++++++------------------ 2 files changed, 75 insertions(+), 43 deletions(-) diff --git a/_CoqProject b/_CoqProject index 67f708ec7..ce0ce7b46 100644 --- a/_CoqProject +++ b/_CoqProject @@ -59,6 +59,7 @@ algebra/frac.v algebra/csum.v algebra/list.v algebra/updates.v +algebra/gset.v program_logic/model.v program_logic/adequacy.v program_logic/hoare_lifting.v diff --git a/algebra/gset.v b/algebra/gset.v index 79958aa8f..06fd34e7d 100644 --- a/algebra/gset.v +++ b/algebra/gset.v @@ -1,46 +1,77 @@ -From iris.algebra Require Export gmap. -From iris.algebra Require Import excl. -From iris.prelude Require Import mapset. +From iris.algebra Require Export cmra. +From iris.algebra Require Import updates. +From iris.prelude Require Export collections gmap. -Definition gsetC K `{Countable K} := gmapC K (exclC unitC). - -Definition to_gsetC `{Countable K} (X : gset K) : gsetC K := - to_gmap (Excl ()) X. +Inductive gset_disj K `{Countable K} := + | GSet : gset K → gset_disj K + | GSetBot : gset_disj K. +Arguments GSet {_ _ _} _. +Arguments GSetBot {_ _ _}. Section gset. -Context `{Countable K}. -Implicit Types X Y : gset K. - -Lemma to_gsetC_empty : to_gsetC (∅ : gset K) = ∅. -Proof. apply to_gmap_empty. Qed. -Lemma to_gsetC_union X Y : X ⊥ Y → to_gsetC X ⋅ to_gsetC Y = to_gsetC (X ∪ Y). -Proof. - intros HXY; apply: map_eq=> i; rewrite /to_gsetC /=. - rewrite lookup_op !lookup_to_gmap. repeat case_option_guard; set_solver. -Qed. -Lemma to_gsetC_valid X : ✓ to_gsetC X. -Proof. intros i. rewrite /to_gsetC lookup_to_gmap. by case_option_guard. Qed. -Lemma to_gsetC_valid_op X Y : ✓ (to_gsetC X ⋅ to_gsetC Y) ↔ X ⊥ Y. -Proof. - split; last (intros; rewrite to_gsetC_union //; apply to_gsetC_valid). - intros HXY i ??; move: (HXY i); rewrite lookup_op !lookup_to_gmap. - rewrite !option_guard_True //. -Qed. - -Context `{Fresh K (gset K), !FreshSpec K (gset K)}. -Lemma updateP_alloc_strong (Q : gsetC K → Prop) (I : gset K) X : - (∀ i, i ∉ X → i ∉ I → Q (to_gsetC ({[i]} ∪ X))) → to_gsetC X ~~>: Q. -Proof. - intros; apply updateP_alloc_strong with I (Excl ()); [done|]=> i. - rewrite /to_gsetC lookup_to_gmap_None -to_gmap_union_singleton; eauto. -Qed. -Lemma updateP_alloc (Q : gsetC K → Prop) X : - (∀ i, i ∉ X → Q (to_gsetC ({[i]} ∪ X))) → to_gsetC X ~~>: Q. -Proof. move=>??. eapply updateP_alloc_strong with (I:=∅); by eauto. Qed. -Lemma updateP_alloc_strong' (I : gset K) X : - to_gsetC X ~~>: λ Y : gsetC K, ∃ i, Y = to_gsetC ({[ i ]} ∪ X) ∧ i ∉ I ∧ i ∉ X. -Proof. eauto using updateP_alloc_strong. Qed. -Lemma updateP_alloc' X : - to_gsetC X ~~>: λ Y : gsetC K, ∃ i, Y = to_gsetC ({[ i ]} ∪ X) ∧ i ∉ X. -Proof. eauto using updateP_alloc. Qed. -End gset. \ No newline at end of file + Context `{Countable K}. + Arguments op _ _ !_ !_ /. + + Canonical Structure gset_disjC := leibnizC (gset_disj K). + + Instance gset_disj_valid : Valid (gset_disj K) := λ X, + match X with GSet _ => True | GSetBot => False end. + Instance gset_disj_empty : Empty (gset_disj K) := GSet ∅. + Instance gset_disj_op : Op (gset_disj K) := λ X Y, + match X, Y with + | GSet X, GSet Y => if decide (X ⊥ Y) then GSet (X ∪ Y) else GSetBot + | _, _ => GSetBot + end. + Instance gset_disj_pcore : PCore (gset_disj K) := λ _, Some ∅. + + Ltac gset_disj_solve := + repeat (simpl || case_decide); + first [apply (f_equal GSet)|done|exfalso]; set_solver by eauto. + + Lemma gset_disj_valid_inv_l X Y : ✓ (GSet X ⋅ Y) → ∃ Y', Y = GSet Y' ∧ X ⊥ Y'. + Proof. destruct Y; repeat (simpl || case_decide); by eauto. Qed. + Lemma gset_disj_union X Y : X ⊥ Y → GSet X ⋅ GSet Y = GSet (X ∪ Y). + Proof. intros. by rewrite /= decide_True. Qed. + Lemma gset_disj_valid_op X Y : ✓ (GSet X ⋅ GSet Y) ↔ X ⊥ Y. + Proof. simpl. case_decide; by split. Qed. + + Lemma gset_disj_ra_mixin : RAMixin (gset_disj K). + Proof. + apply ra_total_mixin; eauto. + - intros [?|]; destruct 1; gset_disj_solve. + - by constructor. + - by destruct 1. + - intros [X1|] [X2|] [X3|]; gset_disj_solve. + - intros [X1|] [X2|]; gset_disj_solve. + - intros [X|]; gset_disj_solve. + - exists (GSet ∅); gset_disj_solve. + - intros [X1|] [X2|]; gset_disj_solve. + Qed. + Canonical Structure gset_disjR := discreteR (gset_disj K) gset_disj_ra_mixin. + + Lemma gset_disj_ucmra_mixin : UCMRAMixin (gset_disj K). + Proof. split; try apply _ || done. intros [X|]; gset_disj_solve. Qed. + Canonical Structure gset_disjUR := + discreteUR (gset_disj K) gset_disj_ra_mixin gset_disj_ucmra_mixin. + + Context `{Fresh K (gset K), !FreshSpec K (gset K)}. + Arguments op _ _ _ _ : simpl never. + + Lemma updateP_alloc_strong (Q : gset_disj K → Prop) (I : gset K) X : + (∀ i, i ∉ X → i ∉ I → Q (GSet ({[i]} ∪ X))) → GSet X ~~>: Q. + Proof. + intros HQ; apply cmra_discrete_updateP=> ? /gset_disj_valid_inv_l [Y [->?]]. + destruct (exist_fresh (X ∪ Y ∪ I)) as [i ?]. + exists (GSet ({[ i ]} ∪ X)); split. + - apply HQ; set_solver by eauto. + - apply gset_disj_valid_op. set_solver by eauto. + Qed. + Lemma updateP_alloc (Q : gset_disj K → Prop) X : + (∀ i, i ∉ X → Q (GSet ({[i]} ∪ X))) → GSet X ~~>: Q. + Proof. move=>??. eapply updateP_alloc_strong with (I:=∅); by eauto. Qed. + Lemma updateP_alloc_strong' (I : gset K) X : + GSet X ~~>: λ Y, ∃ i, Y = GSet ({[ i ]} ∪ X) ∧ i ∉ I ∧ i ∉ X. + Proof. eauto using updateP_alloc_strong. Qed. + Lemma updateP_alloc' X : GSet X ~~>: λ Y, ∃ i, Y = GSet ({[ i ]} ∪ X) ∧ i ∉ X. + Proof. eauto using updateP_alloc. Qed. +End gset. -- GitLab