From f64e97f06c27647f0e8f12293c768c5b9889ced8 Mon Sep 17 00:00:00 2001
From: Ralf Jung <jung@mpi-sws.org>
Date: Sun, 15 Feb 2015 15:11:05 +0100
Subject: [PATCH] add first version of RA (resource algebra): validity is a
 decidable predicate, rather than hard-coded into the type structure

---
 lib/ModuRes/Makefile |   1 +
 lib/ModuRes/RA.v     | 254 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 255 insertions(+)
 create mode 100644 lib/ModuRes/RA.v

diff --git a/lib/ModuRes/Makefile b/lib/ModuRes/Makefile
index daf2da630..d4e480c96 100644
--- a/lib/ModuRes/Makefile
+++ b/lib/ModuRes/Makefile
@@ -89,6 +89,7 @@ VFILES:=BI.v\
   MetricRec.v\
   PCBUltInst.v\
   PCM.v\
+  RA.v\
   Predom.v\
   PreoMet.v\
   UPred.v
diff --git a/lib/ModuRes/RA.v b/lib/ModuRes/RA.v
new file mode 100644
index 000000000..9d6b7b1ca
--- /dev/null
+++ b/lib/ModuRes/RA.v
@@ -0,0 +1,254 @@
+(** Resource algebras: Commutative monoids with a decidable validity predicate. *)
+
+Require Import Bool.
+Require Export Predom.
+Require Import MetricCore.
+Require Import PreoMet.
+
+Class Associative {T} `{eqT : Setoid T} (op : T -> T -> T) :=
+  assoc : forall t1 t2 t3, op t1 (op t2 t3) == op (op t1 t2) t3.
+Class Commutative {T} `{eqT : Setoid T} (op : T -> T -> T) :=
+  comm  : forall t1 t2, op t1 t2 == op t2 t1.
+
+Section Definitions.
+  Context (T : Type) `{Setoid T}.
+
+  Class RA_unit := ra_unit : T.
+  Class RA_op   := ra_op : T -> T -> T.
+  Class RA_valid:= ra_valid : T -> bool.
+  Class RA {TU : RA_unit} {TOP : RA_op} {TV : RA_valid}: Prop :=
+    mkRA {
+        ra_op_proper       :> Proper (equiv ==> equiv ==> equiv) ra_op;
+        ra_op_assoc        :> Associative ra_op;
+        ra_op_comm         :> Commutative ra_op;
+        ra_op_unit t       : ra_op ra_unit t == t;
+        ra_valid_proper    :> Proper (equiv ==> eq) ra_valid;
+        ra_valid_unit      : ra_valid ra_unit = true;
+        ra_op_invalid t1 t2: ra_valid t1 = false -> ra_valid (ra_op t1 t2) = false
+      }.
+End Definitions.
+
+Notation "1" := (ra_unit _) : ra_scope.
+Notation "p · q" := (ra_op _ p q) (at level 40, left associativity) : ra_scope.
+Notation "'valid' p" := (ra_valid _ p) (at level 35) : ra_scope.
+
+Delimit Scope ra_scope with ra.
+
+(* General RA lemmas *)
+Section RAs.
+  Context {T} `{RA T}.
+  Local Open Scope ra_scope.
+
+  Lemma ra_op_unit2 t: t · 1 == t.
+  Proof.
+    rewrite comm. now eapply ra_op_unit.
+  Qed.
+
+  Lemma ra_op_invalid2 t1 t2: valid t2 = false -> valid (t1 · t2) = false.
+  Proof.
+    rewrite comm. now eapply ra_op_invalid.
+  Qed.
+
+  Lemma ra_op_valid t1 t2: valid (t1 · t2) = true -> valid t1 = true.
+  Proof.
+    intros Hval.
+    destruct (valid t1) eqn:Heq; [reflexivity|].
+    rewrite <-Hval. symmetry. now eapply ra_op_invalid.
+  Qed.
+
+  Lemma ra_op_valid2 t1 t2: valid (t1 · t2) = true -> valid t2 = true.
+  Proof.
+    rewrite comm. now eapply ra_op_valid.
+  Qed.
+End RAs.
+
+(* RAs with cartesian products of carriers. *)
+Section Products.
+  Context S T `{raS : RA S, raT : RA T}.
+  Local Open Scope ra_scope.
+
+  Global Instance ra_unit_prod : RA_unit (S * T) := (ra_unit S, ra_unit T).
+  Global Instance ra_op_prod : RA_op (S * T) :=
+    fun st1 st2 =>
+      match st1, st2 with
+        | (s1, t1), (s2, t2) => (s1 · s2, t1 · t2)
+      end.
+  Global Instance ra_valid_prod : RA_valid (S * T) :=
+    fun st => match st with (s, t) =>
+                            valid s && valid t
+              end.
+  Global Instance ra_prod : RA (S * T).
+  Proof.
+    split.
+    - intros [s1 t1] [s2 t2] [Heqs Heqt]. intros [s'1 t'1] [s'2 t'2] [Heqs' Heqt']. simpl in *.
+      split; [rewrite Heqs, Heqs'|rewrite Heqt, Heqt']; reflexivity.
+    - intros [s1 t1] [s2 t2] [s3 t3]. simpl; split; now rewrite ra_op_assoc.
+    - intros [s1 t1] [s2 t2]. simpl; split; now rewrite ra_op_comm.
+    - intros [s t]. simpl; split; now rewrite ra_op_unit.
+    - intros [s1 t1] [s2 t2] [Heqs Heqt]. unfold ra_valid; simpl in *.
+      rewrite Heqs, Heqt. reflexivity.
+    - unfold ra_unit, ra_valid; simpl. erewrite !ra_valid_unit by apply _. reflexivity.
+    - intros [s1 t1] [s2 t2]. unfold ra_valid; simpl. rewrite !andb_false_iff. intros [Hv|Hv].
+      + left. now eapply ra_op_invalid.
+      + right. now eapply ra_op_invalid.
+  Qed.
+
+End Products.
+
+Section PositiveCarrier.
+  Context {T} `{raT : RA T}.
+  Local Open Scope ra_scope.
+
+  Definition ra_pos: Type := { r | valid r = true }.
+  Coercion ra_proj (t:ra_pos): T := proj1_sig t.
+
+  Definition ra_mk_pos t (VAL: valid t = true): ra_pos := exist _ t VAL.
+
+  Program Definition ra_pos_unit: ra_pos := exist _ 1 _.
+  Next Obligation.
+    now erewrite ra_valid_unit by apply _.
+  Qed.
+
+  Lemma ra_pos_mult_valid t1 t2 t:
+    t1 · t2 == ra_proj t -> valid t1 = true.
+  Proof.
+    destruct t as [t Hval]; simpl. intros Heq. rewrite <-Heq in Hval.
+    eapply ra_op_valid. eassumption.
+  Qed.
+
+  Lemma ra_pos_mult_valid2 t1 t2 t:
+    t1 · t2 == ra_proj t -> valid t2 = true.
+  Proof.
+    rewrite comm. now eapply ra_pos_mult_valid.
+  Qed.
+
+End PositiveCarrier.
+Global Arguments ra_pos T {_}.
+
+
+Section Order.
+  Context T `{raT : RA T}.
+  Local Open Scope ra_scope.
+
+  Definition ra_ord (t1 t2 : ra_pos T) :=
+    exists td, (ra_proj td) · (ra_proj t1) == (ra_proj t2).
+
+  Global Program Instance RA_preo : preoType (ra_pos T) | 0 := mkPOType ra_ord.
+  Next Obligation.
+    split.
+    - intros x; exists ra_pos_unit. simpl. erewrite ra_op_unit by apply _; reflexivity.
+    - intros z yz xyz [y Hyz] [x Hxyz]; unfold ra_ord.
+      rewrite <- Hyz, assoc in Hxyz; setoid_rewrite <- Hxyz.
+      assert (VAL:valid (ra_proj x · ra_proj y) = true).
+      { now eapply ra_pos_mult_valid in Hxyz. }
+      exists (ra_mk_pos (ra_proj x · ra_proj y) VAL). reflexivity.
+  Qed.
+
+(*  Definition opcm_ord (t1 t2 : option T) :=
+    exists otd, otd · t1 == t2.
+  Global Program Instance opcm_preo : preoType (option T) :=
+    mkPOType opcm_ord.
+  Next Obligation.
+    split.
+    - intros r; exists 1; erewrite pcm_op_unit by apply _; reflexivity.
+    - intros z yz xyz [y Hyz] [x Hxyz]; exists (x · y).
+      rewrite <- Hxyz, <- Hyz; symmetry; apply assoc.
+  Qed.
+
+  Global Instance equiv_pord_pcm : Proper (equiv ==> equiv ==> equiv) (pord (T := option T)).
+  Proof.
+    intros s1 s2 EQs t1 t2 EQt; split; intros [s HS].
+    - exists s; rewrite <- EQs, <- EQt; assumption.
+    - exists s; rewrite EQs, EQt; assumption.
+  Qed.
+
+  Global Instance pcm_op_monic : Proper (pord ==> pord ==> pord) (pcm_op _).
+  Proof.
+    intros x1 x2 [x EQx] y1 y2 [y EQy]; exists (x · y).
+    rewrite <- assoc, (comm y), <- assoc, assoc, (comm y1), EQx, EQy; reflexivity.
+  Qed.
+
+  Lemma ord_res_optRes r s :
+    (r ⊑ s) <-> (Some r ⊑ Some s).
+  Proof.
+    split; intros HR.
+     - destruct HR as [d EQ]; exists (Some d); assumption.
+     - destruct HR as [[d |] EQ]; [exists d; assumption |].
+       erewrite pcm_op_zero in EQ by apply _; contradiction.
+  Qed.
+
+  Lemma unit_min r : pcm_unit _ ⊑ r.
+  Proof.
+    exists r; now erewrite comm, pcm_op_unit by apply _.
+  Qed.*)
+
+End Order.
+
+Section Exclusive.
+  Context (T: Type) `{Setoid T}.
+  Local Open Scope ra_scope.
+
+  Inductive ra_res_ex: Type :=
+  | ex_own: T -> ra_res_ex
+  | ex_unit: ra_res_ex
+  | ex_bot: ra_res_ex.
+
+  Definition ra_res_ex_eq e1 e2: Prop :=
+    match e1, e2 with
+      | ex_own s1, ex_own s2 => s1 == s2
+      | ex_unit, ex_unit => True
+      | ex_bot, ex_bot => True
+      | _, _ => False
+    end.
+
+  Global Program Instance ra_type_ex : Setoid ra_res_ex :=
+    mkType ra_res_ex_eq.
+  Next Obligation.
+    split.
+    - intros [t| |]; simpl; now auto.
+    - intros [t1| |] [t2| |]; simpl; now auto.
+    - intros [t1| |] [t2| |] [t3| |]; simpl; try now auto.
+      + intros ? ?. etransitivity; eassumption.
+  Qed.
+      
+  Global Instance ra_unit_ex : RA_unit ra_res_ex := ex_unit.
+  Global Instance ra_op_ex : RA_op ra_res_ex :=
+    fun e1 e2 =>
+      match e1, e2 with
+        | ex_own s1, ex_unit => ex_own s1
+        | ex_unit, ex_own s2 => ex_own s2
+        | ex_unit, ex_unit   => ex_unit
+        | _, _               => ex_bot
+      end.
+  Global Instance ra_valid_ex : RA_valid ra_res_ex :=
+    fun e => match e with
+               | ex_bot => false
+               | _      => true
+             end.
+  
+  Global Instance ra_ex : RA ra_res_ex.
+  Proof.
+    split.
+    - intros [t1| |] [t2| |] Heqt [t'1| |] [t'2| |] Heqt'; simpl; now auto.  
+    - intros [s1| |] [s2| |] [s3| |]; reflexivity.
+    - intros [s1| |] [s2| |]; reflexivity.
+    - intros [s1| |]; reflexivity.
+    - intros [t1| |] [t2| |] Heqt; unfold ra_valid; simpl in *; now auto.
+    - reflexivity.
+    - intros [t1| |] [t2| |]; unfold ra_valid; simpl; now auto.
+  Qed.
+
+End Exclusive.
+
+
+(* Package of a monoid as a module type (for use with other modules). *)
+Module Type RA_T.
+
+  Parameter res : Type.
+  Declare Instance res_type : Setoid res.
+  Declare Instance res_op : RA_op res.
+  Declare Instance res_unit : RA_unit res.
+  Declare Instance res_valid : RA_valid res.
+  Declare Instance res_ra : RA res.
+
+End RA_T.
-- 
GitLab