diff --git a/scripts/wordlist.pws b/scripts/wordlist.pws index c0161e2d39239b54e689f129f27d435646e41074..a07fcdf0268cc0be00cd1a91be78706d5b3c99b5 100644 --- a/scripts/wordlist.pws +++ b/scripts/wordlist.pws @@ -39,4 +39,5 @@ Layland Liu sequentiality equalities -extremum \ No newline at end of file +extremum +supremum diff --git a/util/all.v b/util/all.v index 507076a4ac4d1a44e701f7b9aa9a39355a7027da..de8a34786e71185fc347195dc51be38e0a0a85dd 100644 --- a/util/all.v +++ b/util/all.v @@ -13,5 +13,6 @@ Require Export rt.util.epsilon. Require Export rt.util.search_arg. Require Export rt.util.rel. Require Export rt.util.minmax. +Require Export rt.util.supremum. Require Export rt.util.nondecreasing. Require Export rt.util.rewrite_facilities. diff --git a/util/supremum.v b/util/supremum.v new file mode 100644 index 0000000000000000000000000000000000000000..78bdec9d80a2c15fcea5929432f1c08dcddbe13c --- /dev/null +++ b/util/supremum.v @@ -0,0 +1,126 @@ +From mathcomp Require Import ssreflect ssrbool eqtype seq. + +(** * Computation of a Sequence's Supremum *) + +(** This module provides a simple function [supremum] for the computation of a + maximal element of a sequence, according to any given relation [R]. If the + relation [R] is reflexive, total, and transitive, the result of [supremum] + is indeed the supremum of the set of items in the sequence. *) + +Section SelectSupremum. + + (** Consider any type of elements with decidable equality... *) + Context {T : eqType}. + + (** ...and any given relation [R]. *) + Variable R : rel T. + + (** We first define a help function [choose_superior] that, given an element + [x] and maybe a second element [y], picks [x] if [R x y] holds, and [y] + otherwise. *) + Definition choose_superior (x : T) (maybe_y : option T) : option T := + match maybe_y with + | Some y => if R x y then Some x else Some y + | None => Some x + end. + + (** The supremum of a given sequence [s] can then be computed by simply + folding [s] with [choose_superior]. *) + Definition supremum (s : seq T) : option T := foldr choose_superior None s. + + (** Next, we establish that [supremum] satisfies its specification. To this + end, we first establish a few simple helper lemmas. *) + + (** We start with observing how [supremum] can be unrolled one step. *) + Lemma supremum_unfold: + forall head tail, + supremum (head :: tail) = choose_superior head (supremum tail). + Proof. + move=> head tail. + by rewrite [LHS]/supremum /foldr -/(foldr choose_superior None tail) -/(supremum tail). + Qed. + + (** Next, we observe that [supremum] returns a result for any non-empty + list. *) + Lemma supremum_exists: forall x s, x \in s -> supremum s != None. + Proof. + move=> x s IN. + elim: s IN; first by done. + move=> a l _ _. + rewrite supremum_unfold. + destruct (supremum l); rewrite /choose_superior //. + by destruct (R a s). + Qed. + + (** Conversely, if [supremum] finds nothing, then the list is empty. *) + Lemma supremum_none: forall s, supremum s = None -> s = nil. + Proof. + move=> s. + elim: s; first by done. + move => a l IH. + rewrite supremum_unfold /choose_superior. + by destruct (supremum l); try destruct (R a s). + Qed. + + (** Next, we observe that the value found by [supremum] comes indeed from the + list that it was given. *) + Lemma supremum_in: + forall x s, + supremum s = Some x -> + x \in s. + Proof. + move=> x. + elim => // a l IN_TAIL IN. + rewrite in_cons; apply /orP. + move: IN; rewrite supremum_unfold. + destruct (supremum l); rewrite /choose_superior. + { elim: (R a s) => EQ. + - left; apply /eqP. + by injection EQ. + - right; by apply IN_TAIL. } + { left. apply /eqP. + by injection IN. } + Qed. + + (** To prove that [supremum] indeed computes the given sequence's supremum, + we need to make additional assumptions on [R]. *) + + (** (1) [R] is reflexive. *) + Hypothesis H_R_reflexive: reflexive R. + (** (2) [R] is total. *) + Hypothesis H_R_total: total R. + (** (3) [R] is transitive. *) + Hypothesis H_R_transitive: transitive R. + + (** Based on these assumptions, we show that the function [supremum] indeed + computes an upper bound on all elements in the given sequence. *) + Lemma supremum_spec: + forall x s, + supremum s = Some x -> + forall y, + y \in s -> R x y. + Proof. + move=> x s SOME_x. + move: x SOME_x (supremum_in _ _ SOME_x). + elim: s; first by done. + move=> s1 sn IH z SOME_z IN_z_s y. + move: SOME_z. rewrite supremum_unfold /choose_superior => SOME_z. + destruct (supremum sn) as [b|] eqn:SUPR; last first. + { apply supremum_none in SUPR; subst. + rewrite mem_seq1 => /eqP ->. + by injection SOME_z => ->. } + { rewrite in_cons => /orP [/eqP EQy | INy]; last first. + - have R_by: R b y + by apply IH => //; apply supremum_in. + apply H_R_transitive with (y := b) => //. + destruct (R s1 b) eqn:R_s1b; + by injection SOME_z => <-. + - move: IN_z_s; rewrite in_cons => /orP [/eqP EQz | INz]; + first by subst. + move: (H_R_total s1 b) => /orP [R_s1b|R_bs1]. + + move: SOME_z. rewrite R_s1b => SOME_z. + by injection SOME_z => EQ; subst. + + by destruct (R s1 b); injection SOME_z => EQ; subst. } + Qed. + +End SelectSupremum.