From 812f01bf5f64c03a24c28e5d3c29ef01c73d394b Mon Sep 17 00:00:00 2001
From: Dan Frumin <dfrumin@cs.ru.nl>
Date: Fri, 19 Apr 2019 17:49:26 +0200
Subject: [PATCH] gmultiset lemmas

---
 theories/fin_sets.v  | 24 ++++++++++++++++++++++++
 theories/gmultiset.v | 34 ++++++++++++++++++++++++++++++----
 theories/list.v      | 10 ++++++++++
 3 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/theories/fin_sets.v b/theories/fin_sets.v
index 2e517e29..c34f2045 100644
--- a/theories/fin_sets.v
+++ b/theories/fin_sets.v
@@ -101,6 +101,14 @@ Proof.
   apply Permutation_singleton. by rewrite <-(right_id ∅ (∪) {[x]}),
     elements_union_singleton, elements_empty by set_solver.
 Qed.
+Lemma elements_disj_union (X Y : C) :
+  X ## Y → elements (X ∪ Y) ≡ₚ elements X ++ elements Y.
+Proof.
+  intros HXY. apply NoDup_Permutation.
+  - apply NoDup_elements.
+  - apply NoDup_app. set_solver by eauto using NoDup_elements.
+  - set_solver.
+Qed.
 Lemma elements_submseteq X Y : X ⊆ Y → elements X ⊆+ elements Y.
 Proof.
   intros; apply NoDup_submseteq; eauto using NoDup_elements.
@@ -222,6 +230,22 @@ Lemma set_fold_proper {B} (R : relation B) `{!Equivalence R}
   Proper ((≡) ==> R) (set_fold f b : C → B).
 Proof. intros ?? E. apply (foldr_permutation R f b); auto. by rewrite E. Qed.
 
+Lemma set_fold_empty {B} (f : A → B → B) (b : B) :
+  set_fold f b (∅ : C) = b.
+Proof. by unfold set_fold; simpl; rewrite elements_empty. Qed.
+Lemma set_fold_singleton {B} (f : A → B → B) (b : B) (a : A) :
+  set_fold f b ({[a]} : C) = f a b.
+Proof. by unfold set_fold; simpl; rewrite elements_singleton. Qed.
+Lemma set_fold_disj_union (f : A → A → A) (b : A) X Y :
+  Comm (=) f →
+  Assoc (=) f →
+  X ## Y →
+  set_fold f b (X ∪ Y) = set_fold f (set_fold f b X) Y.
+Proof.
+  intros Hcomm Hassoc Hdisj. unfold set_fold; simpl.
+  by rewrite elements_disj_union, <- foldr_app, (comm (++)).
+Qed.
+
 (** * Minimal elements *)
 Lemma minimal_exists R `{!Transitive R, ∀ x y, Decision (R x y)} (X : C) :
   X ≢ ∅ → ∃ x, x ∈ X ∧ minimal R x X.
diff --git a/theories/gmultiset.v b/theories/gmultiset.v
index ace17583..4c83c319 100644
--- a/theories/gmultiset.v
+++ b/theories/gmultiset.v
@@ -330,7 +330,23 @@ Proof.
   destruct (X !! x); naive_solver lia.
 Qed.
 
-(* Properties of the size operation *)
+(** Properties of the set_fold operation *)
+Lemma gmultiset_set_fold_empty {B} (f : A → B → B) (b : B) :
+  set_fold f b (∅ : gmultiset A) = b.
+Proof. by unfold set_fold; simpl; rewrite gmultiset_elements_empty. Qed.
+Lemma gmultiset_set_fold_singleton {B} (f : A → B → B) (b : B) (a : A) :
+  set_fold f b ({[a]} : gmultiset A) = f a b.
+Proof. by unfold set_fold; simpl; rewrite gmultiset_elements_singleton. Qed.
+Lemma gmultiset_set_fold_disj_union (f : A → A → A) (b : A) X Y :
+  Comm (=) f →
+  Assoc (=) f →
+  set_fold f b (X ⊎ Y) = set_fold f (set_fold f b X) Y.
+Proof.
+  intros Hcomm Hassoc. unfold set_fold; simpl.
+  by rewrite gmultiset_elements_disj_union, <- foldr_app, (comm (++)).
+Qed.
+
+(** Properties of the size operation *)
 Lemma gmultiset_size_empty : size (∅ : gmultiset A) = 0.
 Proof. done. Qed.
 Lemma gmultiset_size_empty_inv X : size X = 0 → X = ∅.
@@ -370,7 +386,7 @@ Proof.
   by rewrite gmultiset_elements_disj_union, app_length.
 Qed.
 
-(* Order stuff *)
+(** Order stuff *)
 Global Instance gmultiset_po : PartialOrder (⊆@{gmultiset A}).
 Proof.
   split; [split|].
@@ -464,6 +480,13 @@ Proof.
   rewrite HX at 2; rewrite gmultiset_size_disj_union. lia.
 Qed.
 
+Lemma gmultiset_empty_difference X Y : Y ⊆ X → Y ∖ X = ∅.
+Proof.
+  intros HYX. unfold_leibniz. intros x.
+  rewrite multiplicity_difference, multiplicity_empty.
+  specialize (HYX x). lia.
+Qed.
+
 Lemma gmultiset_non_empty_difference X Y : X ⊂ Y → Y ∖ X ≠ ∅.
 Proof.
   intros [_ HXY2] Hdiff; destruct HXY2; intros x.
@@ -471,13 +494,16 @@ Proof.
   rewrite multiplicity_difference, multiplicity_empty; lia.
 Qed.
 
+Lemma gmultiset_difference_diag X : X ∖ X = ∅.
+Proof. by apply gmultiset_empty_difference. Qed.
+
 Lemma gmultiset_difference_subset X Y : X ≠ ∅ → X ⊆ Y → Y ∖ X ⊂ Y.
 Proof.
   intros. eapply strict_transitive_l; [by apply gmultiset_union_subset_r|].
   by rewrite <-(gmultiset_disj_union_difference X Y).
 Qed.
 
-(* Mononicity *)
+(** Mononicity *)
 Lemma gmultiset_elements_submseteq X Y : X ⊆ Y → elements X ⊆+ elements Y.
 Proof.
   intros ->%gmultiset_disj_union_difference. rewrite gmultiset_elements_disj_union.
@@ -495,7 +521,7 @@ Proof.
     gmultiset_size_disj_union by auto. lia.
 Qed.
 
-(* Well-foundedness *)
+(** Well-foundedness *)
 Lemma gmultiset_wf : wf (⊂@{gmultiset A}).
 Proof.
   apply (wf_projected (<) size); auto using gmultiset_subset_size, lt_wf.
diff --git a/theories/list.v b/theories/list.v
index 8194d802..a38fc6a0 100644
--- a/theories/list.v
+++ b/theories/list.v
@@ -3446,6 +3446,16 @@ Lemma foldr_permutation_proper {A B} (R : relation B) `{!PreOrder R}
     (Hf : ∀ a1 a2 b, R (f a1 (f a2 b)) (f a2 (f a1 b))) :
   Proper ((≡ₚ) ==> R) (foldr f b).
 Proof. intros l1 l2 Hl. apply foldr_permutation; auto. Qed.
+Instance foldr_permutation_proper' {A} (R : relation A) `{!PreOrder R}
+    (f : A → A → A) (a : A) `{!∀ a, Proper (R ==> R) (f a), !Assoc R f, !Comm R f} :
+  Proper ((≡ₚ) ==> R) (foldr f a).
+Proof.
+  apply (foldr_permutation_proper R f); [solve_proper|].
+  assert (Proper (R ==> R ==> R) f).
+  { intros a1 a2 Ha b1 b2 Hb. by rewrite Hb, (comm f a1), Ha, (comm f). }
+  intros a1 a2 b.
+  by rewrite (assoc f), (comm f _ b), (assoc f), (comm f b), (comm f _ a2).
+Qed.
 
 (** ** Properties of the [zip_with] and [zip] functions *)
 Section zip_with.
-- 
GitLab