diff --git a/analysis/facts/model/task_arrivals.v b/analysis/facts/model/task_arrivals.v index 73cbb564aff2a9bb2f86538dd8311db48c238f8a..d02db76ac6d742b55345f673dd60a70526bc5319 100644 --- a/analysis/facts/model/task_arrivals.v +++ b/analysis/facts/model/task_arrivals.v @@ -230,7 +230,7 @@ Section TaskArrivals. Proof. intros *. rewrite /task_arrivals_between /task_arrivals_at /arrivals_between. - now apply cat_filter_eq_filter_cat. + now apply bigcat_nat_filter_eq_filter_bigcat_nat. Qed. (** The number of jobs of a task [tsk] in the interval <<[t1, t2)>> is the same @@ -242,7 +242,7 @@ Section TaskArrivals. Proof. intros *. rewrite /task_arrivals_between /task_arrivals_at /arrivals_between. - now rewrite size_big_nat cat_filter_eq_filter_cat. + now rewrite size_big_nat bigcat_nat_filter_eq_filter_bigcat_nat. Qed. End TaskArrivals. diff --git a/util/bigcat.v b/util/bigcat.v index 1444b8dccc27fcbc1f5b0de561d19998ebb9b00e..85fb9f22063e282476f9350e3e050c2837e4c7e6 100644 --- a/util/bigcat.v +++ b/util/bigcat.v @@ -1,10 +1,10 @@ Require Export prosa.util.tactics prosa.util.notation. From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop. -Require Export prosa.util.tactics prosa.util.ssrlia. +Require Export prosa.util.tactics prosa.util.ssrlia prosa.util.list. -(** In this section, we introduce useful lemmas about the concatenation operation performed - over an arbitrary range of sequences. *) -Section BigCatLemmas. +(** In this section, we introduce useful lemmas about the concatenation operation + performed over arbitrary sequences. *) +Section BigCatNatLemmas. (** Consider any type supporting equality comparisons... *) Variable T: eqType. @@ -14,7 +14,7 @@ Section BigCatLemmas. (** In this section, we prove that the concatenation over sequences works as expected: no element is lost during the concatenation, and no new element is introduced. *) - Section BigCatElements. + Section BigCatNatElements. (** First, we show that the concatenation comprises all the elements of each sequence; i.e. any element contained in one of the sequences will also be an element of the @@ -30,9 +30,9 @@ Section BigCatLemmas. rewrite mem_cat; apply/orP; right. destruct n; first by rewrite ltn0 in LE0. rewrite big_nat_recl; last by ins. - by rewrite mem_cat; apply/orP; left. + by rewrite mem_cat; apply/orP; left. Qed. - + (** Conversely, we prove that any element belonging to a concatenation of sequences must come from one of the sequences. *) Lemma mem_bigcat_nat_exists: @@ -46,15 +46,14 @@ Section BigCatLemmas. destruct (leqP m n); last by rewrite big_geq ?in_nil // ltnW in IN. rewrite big_nat_recr // /= mem_cat in IN. move: IN => /orP [HEAD | TAIL]. - { - apply IHn in HEAD; destruct HEAD; exists x0. move: H => [H /andP [H0 H1]]. + - apply IHn in HEAD; destruct HEAD; exists x0. + move: H => [H /andP [H0 H1]]. split; first by done. - by apply/andP; split; [by done | by apply ltnW]. } - { - exists n; split; first by done. - apply/andP; split; [by done | by apply ltnSn]. } + by apply/andP; split; last by apply ltnW. + - exists n; split; first by done. + by apply/andP; split; last apply ltnSn. Qed. - + Lemma mem_bigcat_ord: forall x n (j: 'I_n) (f: 'I_n -> list T), j < n -> @@ -64,24 +63,24 @@ Section BigCatLemmas. move=> x; elim=> [//|n IHn] j f' Hj Hx. rewrite big_ord_recr /= mem_cat; apply /orP. move: Hj; rewrite ltnS leq_eqVlt => /orP [/eqP Hj|Hj]. - { by right; rewrite (_ : ord_max = j); [|apply ord_inj]. } - left. - apply (IHn (Ordinal Hj)); [by []|]. - by set j' := widen_ord _ _; have -> : j' = j; [apply ord_inj|]. + - by right; rewrite (_ : ord_max = j); [|apply ord_inj]. + - left. + apply (IHn (Ordinal Hj)); [by []|]. + by set j' := widen_ord _ _; have -> : j' = j; [apply ord_inj|]. Qed. - End BigCatElements. + End BigCatNatElements. (** In this section, we show how we can preserve uniqueness of the elements (i.e. the absence of a duplicate) over a concatenation of sequences. *) - Section BigCatDistinctElements. + Section BigCatNatDistinctElements. (** Assume that there are no duplicates in each of the possible sequences to concatenate... *) - Hypothesis H_uniq_seq: forall i, uniq (f i). + Hypothesis H_uniq_seq : forall i, uniq (f i). (** ...and that there are no elements in common between the sequences. *) - Hypothesis H_no_elements_in_common: + Hypothesis H_no_elements_in_common : forall x i1 i2, x \in f i1 -> x \in f i2 -> i1 = i2. (** We prove that the concatenation will yield a sequence with unique elements. *) @@ -111,14 +110,14 @@ Section BigCatLemmas. forall n (f: 'I_n -> list T), uniq (\cat_(i < n) (f i)) -> (forall x i1 i2, - x \in (f i1) -> x \in (f i2) -> i1 = i2). + x \in (f i1) -> x \in (f i2) -> i1 = i2). Proof. case=> [|n]; [by move=> f' Huniq x; case|]. elim: n => [|n IHn] f' Huniq x i1 i2 Hi1 Hi2. { move: i1 i2 {Hi1 Hi2}; case; case=> [i1|//]; case; case=> [i2|//]. apply f_equal, eq_irrelevance. } - move: (leq_ord i1); rewrite leq_eqVlt => /orP [H'i1|H'i1]; - move: (leq_ord i2); rewrite leq_eqVlt => /orP [H'i2|H'i2]. + move: (leq_ord i1); rewrite leq_eqVlt => /orP [H'i1|H'i1]. + all: move: (leq_ord i2); rewrite leq_eqVlt => /orP [H'i2|H'i2]. { by apply ord_inj; move: H'i1 H'i2 => /eqP -> /eqP ->. } { exfalso. move: Huniq; rewrite big_ord_recr cat_uniq => /andP [_ /andP [H _]]. @@ -145,25 +144,24 @@ Section BigCatLemmas. by apply ord_inj; rewrite /= inordK. Qed. - End BigCatDistinctElements. + End BigCatNatDistinctElements. (** We show that filtering a concatenated sequence by any predicate [P] is the same as concatenating the elements of the sequence that satisfy [P]. *) - Lemma cat_filter_eq_filter_cat: + Lemma bigcat_nat_filter_eq_filter_bigcat_nat: forall {X : Type} (F : nat -> seq X) (P : X -> bool) (t1 t2 : nat), [seq x <- \cat_(t1<=t<t2) F t | P x] = \cat_(t1<=t<t2)[seq x <- F t | P x]. Proof. intros. specialize (leq_total t1 t2) => /orP [T1_LT | T2_LT]. - + have EX: exists Δ, t2 = t1 + Δ by exists (t2 - t1); ssrlia. + + have EX: exists Δ, t2 = t1 + Δ by simpl; exists (t2 - t1); ssrlia. move: EX => [Δ EQ]; subst t2. induction Δ. - { now rewrite addn0 !big_geq => //. } + { by rewrite addn0 !big_geq => //. } { rewrite addnS !big_nat_recr => //=; try by rewrite leq_addr. rewrite filter_cat IHΔ => //. - now ssrlia. - } - + now rewrite !big_geq => //. + by ssrlia. } + + by rewrite !big_geq => //. Qed. (** We show that the size of a concatenated sequence is the same as @@ -175,15 +173,205 @@ Section BigCatLemmas. Proof. intros. specialize (leq_total t1 t2) => /orP [T1_LT | T2_LT]. - + have EX: exists Δ, t2 = t1 + Δ by exists (t2 - t1); ssrlia. + - have EX: exists Δ, t2 = t1 + Δ by simpl; exists (t2 - t1); ssrlia. move: EX => [Δ EQ]; subst t2. induction Δ. - { now rewrite addn0 !big_geq => //. } + { by rewrite addn0 !big_geq => //. } { rewrite addnS !big_nat_recr => //=; try by rewrite leq_addr. rewrite size_cat IHΔ => //. - now ssrlia. - } - + now rewrite !big_geq => //. + by ssrlia. } + - by rewrite !big_geq => //. Qed. - + +End BigCatNatLemmas. + + +(** In this section, we introduce useful lemmas about the concatenation operation + performed over arbitrary sequences. *) +Section BigCatLemmas. + + (** Consider any two types supporting equality comparisons... *) + Variable X Y : eqType. + + (** ...and a function that, given an index, yields a sequence. *) + Variable f : X -> seq Y. + + (** First, we show that the concatenation comprises all the elements of each sequence; + i.e. any element contained in one of the sequences will also be an element of the + result of the concatenation. *) + Lemma mem_bigcat : + forall x y s, + x \in s -> + y \in f x -> + y \in \cat_(x <- s) f x. + Proof. + move=> x y s INs INfx. + induction s; first by done. + rewrite big_cons mem_cat. + move:INs; rewrite in_cons => /orP[/eqP HEAD | CONS]. + - by rewrite -HEAD; apply /orP; left. + - by apply /orP; right; apply IHs. + Qed. + + (** Conversely, we prove that any element belonging to a concatenation of sequences + must come from one of the sequences. *) + Lemma mem_bigcat_exists : + forall s y, + y \in \cat_(x <- s) f x -> + exists x, x \in s /\ y \in f x. + Proof. + induction s; first by rewrite big_nil. + move=> y. + rewrite big_cons mem_cat => /orP[HEAD | CONS]. + - exists a. + by split => //; apply mem_head. + - move: (IHs _ CONS) => [x [INs INfx]]. + exists x; split =>//. + by rewrite in_cons; apply /orP; right. + Qed. + + (** Next, we show that a map and filter operation can be done either + before or after a concatenation, leading to the same result. *) + Lemma bigcat_filter_eq_filter_bigcat: + forall xss P, + [seq x <- \cat_(xs <- xss) f xs | P x] = + \cat_(xs <- xss) [seq x <- f xs | P x] . + Proof. + move=> xss P. + induction xss. + - by rewrite !big_nil. + - by rewrite !big_cons filter_cat IHxss. + Qed. + + (** In this section, we show how we can preserve uniqueness of the elements + (i.e. the absence of a duplicate) over a concatenation of sequences. *) + Section BigCatDistinctElements. + + (** Assume that there are no duplicates in each of the possible + sequences to concatenate... *) + Hypothesis H_uniq_f : forall x, uniq (f x). + + (** ...and that there are no elements in common between the sequences. *) + Hypothesis H_no_elements_in_common : + forall x y z, + x \in f y -> x \in f z -> y = z. + + (** We prove that the concatenation will yield a sequence with unique elements. *) + Lemma bigcat_uniq : + forall xs, + uniq xs -> + uniq (\cat_(x <- xs) (f x)). + Proof. + induction xs; first by rewrite big_nil. + rewrite cons_uniq => /andP [NINxs UNIQ]. + rewrite big_cons cat_uniq. + apply /andP; split; first by apply H_uniq_f. + apply /andP; split; last by apply IHxs. + apply /hasPn=> x IN; apply /negP=> INfa. + move: (mem_bigcat_exists _ _ IN) => [a' [INxs INfa']]. + move: (H_no_elements_in_common x a a' INfa INfa') => EQa. + by move: NINxs; rewrite EQa => /negP CONTRA. + Qed. + + End BigCatDistinctElements. + + (** In this section, we show some properties of the concatenation of + sequences in combination with a function [g] that cancels [f]. *) + Section BigCatWithCancelFunctions. + + (** Consider a function [g]... *) + Variable g : Y -> X. + + (** ... and assume that [g] can cancel [f] starting from an element of + the sequence [f x]. *) + Hypothesis H_g_cancels_f : forall x y, y \in f x -> g y = x. + + (** First, we show that no element of a sequence [f x1] can be fed into + [g] and obtain an element [x2] which differs from [x1]. Hence, filtering + by this condition always leads to the empty sequence. *) + Lemma seq_different_elements_nil : + forall x1 x2, + x1 != x2 -> + [seq x <- f x1 | g x == x2] = [::]. + Proof. + move => x1 x2 => /negP NEQ. + apply filter_in_pred0. + move => y IN; apply/negP => /eqP EQ2. + apply: NEQ; apply/eqP. + move: (H_g_cancels_f _ _ IN) => EQ1. + by rewrite -EQ1 -EQ2. + Qed. + + (** Finally, assume we are given an element [y] which is contained in a + duplicate-free sequence [xs]. Then, [f] is applied to each element of + [xs], but only the elements for which [g] yields [y] are kept. In this + scenario, concatenating the resulting sequences will always lead to [f y]. *) + Lemma bigcat_seq_uniqK : + forall y xs, + y \in xs -> + uniq xs -> + \cat_(x <- xs) [seq x' <- f x | g x' == y] = f y. + Proof. + move=> y xs IN UNI. + induction xs as [ | x' xs]; first by done. + move: IN; rewrite in_cons => /orP [/eqP EQ| IN]. + { subst; rewrite !big_cons. + have -> : [seq x <- f x' | g x == x'] = f x'. + { apply/all_filterP/allP. + intros y IN; apply/eqP. + by apply H_g_cancels_f. } + have ->: \cat_(j<-xs)[seq x <- f j | g x == x'] = [::]; last by rewrite cats0. + rewrite big1_seq //; move => xs2 /andP [_ IN]. + have NEQ: xs2 != x'; last by rewrite seq_different_elements_nil. + apply/neqP; intros EQ; subst x'. + move: UNI; rewrite cons_uniq => /andP [NIN _]. + by move: NIN => /negP NIN; apply: NIN. } + { rewrite big_cons IHxs //; last by move:UNI; rewrite cons_uniq=> /andP[_ ?]. + have NEQ: (x' != y); last by rewrite seq_different_elements_nil. + apply/neqP; intros EQ; subst x'. + move: UNI; rewrite cons_uniq => /andP [NIN _]. + by move: NIN => /negP NIN; apply: NIN. } + Qed. + + End BigCatWithCancelFunctions. + End BigCatLemmas. + +(** In this section, we show that the number of elements of the result + of a nested mapping and concatenation operation is independent from + the order in which the concatenations are performed. *) +Section BigCatNestedCount. + + (** Consider any three types supporting equality comparisons... *) + Variable X Y Z : eqType. + + (** ... a function [F] that, given two indices, yields a sequence... *) + Variable F : X -> Y -> seq Z. + + (** and a predicate [P]. *) + Variable P : pred Z. + + (** Assume that, given two sequences [xs] and [ys], their elements are fed to + [F] in a pair-wise fashion. The resulting lists are then concatenated. + The following lemma shows that, when the operation described above is performed, + the number of elements respecting [P] in the resulting list is the same, regardless + of the order in which [xs] and [ys] are combined. *) + Lemma bigcat_count_exchange : + forall xs ys, + count P (\cat_(x <- xs) \cat_(y <- ys) F x y) = + count P (\cat_(y <- ys) \cat_(x <- xs) F x y). + Proof. + induction xs as [|x0 seqX IHxs]; induction ys as [|y0 seqY IHys]; intros. + { by rewrite !big_nil. } + { by rewrite big_cons count_cat -IHys !big_nil. } + { by rewrite big_cons count_cat IHxs !big_nil. } + { rewrite !big_cons !count_cat. + apply/eqP; rewrite -!addnA eqn_add2l. + rewrite IHxs -IHys !big_cons !count_cat. + rewrite addnC -!addnA eqn_add2l addnC eqn_add2l. + by rewrite IHxs. } + Qed. + +End BigCatNestedCount. + + diff --git a/util/notation.v b/util/notation.v index 63cc0ff600c2a8cb568a7974cb84abc0c656aab2..8a0747f394a2ae37893af0d73be9121a5b5cdaaf 100644 --- a/util/notation.v +++ b/util/notation.v @@ -29,4 +29,17 @@ Reserved Notation "\cat_ ( i < n | P ) F" Notation "\cat_ ( i < n | P ) F" := (\big[cat/[::]]_(i < n | P) F%N) : nat_scope. - \ No newline at end of file + +Reserved Notation "\cat_ ( x <- xs | P ) F" + (at level 41, F at level 41, x, xs at level 50, + format "'[' \cat_ ( x <- xs | P ) '/ ' F ']'"). + +Notation "\cat_ ( x <- xs | P ) F" := + (\big[cat/[::]]_(x <- xs | P) F) : big_scope. + +Reserved Notation "\cat_ ( x <- xs ) F" + (at level 41, F at level 41, x, xs at level 50, + format "'[' \cat_ ( x <- xs ) '/ ' F ']'"). + +Notation "\cat_ ( x <- xs ) F" := + (\big[cat/[::]]_(x <- xs) F) : big_scope.