From a8d022559f33d7ff0f286139bd9fad699683389c Mon Sep 17 00:00:00 2001 From: Johannes Kloos <jkloos@mpi-sws.org> Date: Tue, 31 Oct 2017 11:38:32 +0100 Subject: [PATCH] Generic fresh element generator for infinite types. This implements a simple linear search for fresh elements. --- theories/fin_collections.v | 85 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/theories/fin_collections.v b/theories/fin_collections.v index c2e6487e..942de1ea 100644 --- a/theories/fin_collections.v +++ b/theories/fin_collections.v @@ -283,4 +283,89 @@ Proof. refine (cast_if (decide (Exists P (elements X)))); by rewrite set_Exists_elements. Defined. + +(** * Fresh elements *) +Section Fresh. + Context `{Infinite A, ∀ (x: A) (s: C), Decision (x ∈ s)}. + + Lemma subset_difference_in {x: A} {s: C} (inx: x ∈ s): s ∖ {[ x ]} ⊂ s. + Proof. set_solver. Qed. + + Definition fresh_generic_body (s: C) (rec: ∀ s', s' ⊂ s → nat → A) (n: nat) := + let cand := inject n in + match decide (cand ∈ s) with + | left H => rec _ (subset_difference_in H) (S n) + | right _ => cand + end. + Lemma fresh_generic_body_proper s (f g: ∀ y, y ⊂ s → nat → A): + (∀ y Hy Hy', pointwise_relation nat eq (f y Hy) (g y Hy')) → + pointwise_relation nat eq (fresh_generic_body s f) (fresh_generic_body s g). + Proof. + intros relfg i. + unfold fresh_generic_body. + destruct decide. + 2: done. + apply relfg. + Qed. + + Global Instance fresh_generic: Fresh A C | 20 := + λ s, Fix collection_wf (const (nat → A)) fresh_generic_body s 0. + + Global Instance fresh_generic_spec: FreshSpec A C. + Proof. + assert (unfold: ∀ s n, + Fix collection_wf (const (nat → A)) fresh_generic_body s n = + fresh_generic_body s + (λ s' _ n, Fix collection_wf (const (nat → A)) fresh_generic_body s' n) + n). + { intros. + apply (Fix_unfold_rel collection_wf (const (nat → A)) (const (pointwise_relation nat (=))) + fresh_generic_body fresh_generic_body_proper s n). } + split. + - apply _. + - unfold fresh, fresh_generic. + intro X. + generalize 0 as n. + induction X as [X IH] using (well_founded_ind collection_wf). + intros n Y eqXY. + rewrite (unfold X n), (unfold Y n). + unfold fresh_generic_body at 1 3. + destruct decide as [case|case], decide as [case'|case']. + 2,3: specialize (eqXY (inject n)); tauto. + 2: done. + erewrite (IH (X ∖ {[inject n]})). + + done. + + by apply subset_difference_in. + + by intro; rewrite !elem_of_difference, eqXY. + - unfold fresh, fresh_generic. + intro X. + generalize 0 as n. + induction X as [X IH] using (well_founded_ind collection_wf). + intro. + rewrite unfold; unfold fresh_generic_body at 1. + destruct decide as [case|case]. + 2: done. + specialize (IH _ (subset_difference_in case) (S n)). + rewrite not_elem_of_difference in IH. + destruct IH as [?|contra]. + 1: done. + clear case. + assert (∀ Y n, ∃ m, Fix collection_wf (const (nat → A)) + fresh_generic_body Y n = inject m ∧ n ≤ m) + as candidates. + { clear X n contra. + induction Y as [Y IH] using (well_founded_ind collection_wf). + intro. + setoid_rewrite unfold; unfold fresh_generic_body at 1. + destruct decide as [case|case]. + { destruct (IH _ (subset_difference_in case) (S n)) as [m [eqx bound]]. + exists m; split; auto with arith. } + { exists n; auto. } } + revert contra. + destruct (candidates (X ∖ {[ inject n ]}) (S n)) as [m [-> bound]]. + rewrite elem_of_singleton; intro eqinj. + enough (n = m) by lia. + apply inject_injective; by rewrite eqinj. + Qed. +End Fresh. End fin_collection. -- GitLab