Skip to content
Snippets Groups Projects
Commit 39bd1a26 authored by Marco Maida's avatar Marco Maida Committed by Björn Brandenburg
Browse files

add `bigcat` over sequences

parent aed29c33
No related branches found
No related tags found
1 merge request!125Added `bigcat` over sequences
Pipeline #42702 passed
...@@ -230,7 +230,7 @@ Section TaskArrivals. ...@@ -230,7 +230,7 @@ Section TaskArrivals.
Proof. Proof.
intros *. intros *.
rewrite /task_arrivals_between /task_arrivals_at /arrivals_between. 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. Qed.
(** The number of jobs of a task [tsk] in the interval <<[t1, t2)>> is the same (** The number of jobs of a task [tsk] in the interval <<[t1, t2)>> is the same
...@@ -242,7 +242,7 @@ Section TaskArrivals. ...@@ -242,7 +242,7 @@ Section TaskArrivals.
Proof. Proof.
intros *. intros *.
rewrite /task_arrivals_between /task_arrivals_at /arrivals_between. 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. Qed.
End TaskArrivals. End TaskArrivals.
Require Export prosa.util.tactics prosa.util.notation. Require Export prosa.util.tactics prosa.util.notation.
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop. 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 (** In this section, we introduce useful lemmas about the concatenation operation
over an arbitrary range of sequences. *) performed over arbitrary sequences. *)
Section BigCatLemmas. Section BigCatNatLemmas.
(** Consider any type supporting equality comparisons... *) (** Consider any type supporting equality comparisons... *)
Variable T: eqType. Variable T: eqType.
...@@ -14,7 +14,7 @@ Section BigCatLemmas. ...@@ -14,7 +14,7 @@ Section BigCatLemmas.
(** In this section, we prove that the concatenation over sequences works as expected: (** 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. *) 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; (** 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 i.e. any element contained in one of the sequences will also be an element of the
...@@ -30,9 +30,9 @@ Section BigCatLemmas. ...@@ -30,9 +30,9 @@ Section BigCatLemmas.
rewrite mem_cat; apply/orP; right. rewrite mem_cat; apply/orP; right.
destruct n; first by rewrite ltn0 in LE0. destruct n; first by rewrite ltn0 in LE0.
rewrite big_nat_recl; last by ins. rewrite big_nat_recl; last by ins.
by rewrite mem_cat; apply/orP; left. by rewrite mem_cat; apply/orP; left.
Qed. Qed.
(** Conversely, we prove that any element belonging to a concatenation of sequences (** Conversely, we prove that any element belonging to a concatenation of sequences
must come from one of the sequences. *) must come from one of the sequences. *)
Lemma mem_bigcat_nat_exists: Lemma mem_bigcat_nat_exists:
...@@ -46,15 +46,14 @@ Section BigCatLemmas. ...@@ -46,15 +46,14 @@ Section BigCatLemmas.
destruct (leqP m n); last by rewrite big_geq ?in_nil // ltnW in IN. destruct (leqP m n); last by rewrite big_geq ?in_nil // ltnW in IN.
rewrite big_nat_recr // /= mem_cat in IN. rewrite big_nat_recr // /= mem_cat in IN.
move: IN => /orP [HEAD | TAIL]. move: IN => /orP [HEAD | TAIL].
{ - apply IHn in HEAD; destruct HEAD; exists x0.
apply IHn in HEAD; destruct HEAD; exists x0. move: H => [H /andP [H0 H1]]. move: H => [H /andP [H0 H1]].
split; first by done. split; first by done.
by apply/andP; split; [by done | by apply ltnW]. } by apply/andP; split; last by apply ltnW.
{ - exists n; split; first by done.
exists n; split; first by done. by apply/andP; split; last apply ltnSn.
apply/andP; split; [by done | by apply ltnSn]. }
Qed. Qed.
Lemma mem_bigcat_ord: Lemma mem_bigcat_ord:
forall x n (j: 'I_n) (f: 'I_n -> list T), forall x n (j: 'I_n) (f: 'I_n -> list T),
j < n -> j < n ->
...@@ -64,24 +63,24 @@ Section BigCatLemmas. ...@@ -64,24 +63,24 @@ Section BigCatLemmas.
move=> x; elim=> [//|n IHn] j f' Hj Hx. move=> x; elim=> [//|n IHn] j f' Hj Hx.
rewrite big_ord_recr /= mem_cat; apply /orP. rewrite big_ord_recr /= mem_cat; apply /orP.
move: Hj; rewrite ltnS leq_eqVlt => /orP [/eqP Hj|Hj]. move: Hj; rewrite ltnS leq_eqVlt => /orP [/eqP Hj|Hj].
{ by right; rewrite (_ : ord_max = j); [|apply ord_inj]. } - by right; rewrite (_ : ord_max = j); [|apply ord_inj].
left. - left.
apply (IHn (Ordinal Hj)); [by []|]. apply (IHn (Ordinal Hj)); [by []|].
by set j' := widen_ord _ _; have -> : j' = j; [apply ord_inj|]. by set j' := widen_ord _ _; have -> : j' = j; [apply ord_inj|].
Qed. Qed.
End BigCatElements. End BigCatNatElements.
(** In this section, we show how we can preserve uniqueness of the elements (** 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. *) (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 (** Assume that there are no duplicates in each of the possible
sequences to concatenate... *) 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. *) (** ...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. 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. *) (** We prove that the concatenation will yield a sequence with unique elements. *)
...@@ -111,14 +110,14 @@ Section BigCatLemmas. ...@@ -111,14 +110,14 @@ Section BigCatLemmas.
forall n (f: 'I_n -> list T), forall n (f: 'I_n -> list T),
uniq (\cat_(i < n) (f i)) -> uniq (\cat_(i < n) (f i)) ->
(forall x i1 i2, (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. Proof.
case=> [|n]; [by move=> f' Huniq x; case|]. case=> [|n]; [by move=> f' Huniq x; case|].
elim: n => [|n IHn] f' Huniq x i1 i2 Hi1 Hi2. elim: n => [|n IHn] f' Huniq x i1 i2 Hi1 Hi2.
{ move: i1 i2 {Hi1 Hi2}; case; case=> [i1|//]; case; case=> [i2|//]. { move: i1 i2 {Hi1 Hi2}; case; case=> [i1|//]; case; case=> [i2|//].
apply f_equal, eq_irrelevance. } apply f_equal, eq_irrelevance. }
move: (leq_ord i1); rewrite leq_eqVlt => /orP [H'i1|H'i1]; move: (leq_ord i1); rewrite leq_eqVlt => /orP [H'i1|H'i1].
move: (leq_ord i2); rewrite leq_eqVlt => /orP [H'i2|H'i2]. all: move: (leq_ord i2); rewrite leq_eqVlt => /orP [H'i2|H'i2].
{ by apply ord_inj; move: H'i1 H'i2 => /eqP -> /eqP ->. } { by apply ord_inj; move: H'i1 H'i2 => /eqP -> /eqP ->. }
{ exfalso. { exfalso.
move: Huniq; rewrite big_ord_recr cat_uniq => /andP [_ /andP [H _]]. move: Huniq; rewrite big_ord_recr cat_uniq => /andP [_ /andP [H _]].
...@@ -145,25 +144,24 @@ Section BigCatLemmas. ...@@ -145,25 +144,24 @@ Section BigCatLemmas.
by apply ord_inj; rewrite /= inordK. by apply ord_inj; rewrite /= inordK.
Qed. Qed.
End BigCatDistinctElements. End BigCatNatDistinctElements.
(** We show that filtering a concatenated sequence by any predicate [P] (** We show that filtering a concatenated sequence by any predicate [P]
is the same as concatenating the elements of the sequence that satisfy [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), 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]. [seq x <- \cat_(t1<=t<t2) F t | P x] = \cat_(t1<=t<t2)[seq x <- F t | P x].
Proof. Proof.
intros. intros.
specialize (leq_total t1 t2) => /orP [T1_LT | T2_LT]. 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. move: EX => [Δ EQ]; subst t2.
induction Δ. induction Δ.
{ now rewrite addn0 !big_geq => //. } { by rewrite addn0 !big_geq => //. }
{ rewrite addnS !big_nat_recr => //=; try by rewrite leq_addr. { rewrite addnS !big_nat_recr => //=; try by rewrite leq_addr.
rewrite filter_cat IHΔ => //. rewrite filter_cat IHΔ => //.
now ssrlia. by ssrlia. }
} + by rewrite !big_geq => //.
+ now rewrite !big_geq => //.
Qed. Qed.
(** We show that the size of a concatenated sequence is the same as (** We show that the size of a concatenated sequence is the same as
...@@ -175,15 +173,205 @@ Section BigCatLemmas. ...@@ -175,15 +173,205 @@ Section BigCatLemmas.
Proof. Proof.
intros. intros.
specialize (leq_total t1 t2) => /orP [T1_LT | T2_LT]. 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. move: EX => [Δ EQ]; subst t2.
induction Δ. induction Δ.
{ now rewrite addn0 !big_geq => //. } { by rewrite addn0 !big_geq => //. }
{ rewrite addnS !big_nat_recr => //=; try by rewrite leq_addr. { rewrite addnS !big_nat_recr => //=; try by rewrite leq_addr.
rewrite size_cat IHΔ => //. rewrite size_cat IHΔ => //.
now ssrlia. by ssrlia. }
} - by rewrite !big_geq => //.
+ now rewrite !big_geq => //.
Qed. 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. 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.
...@@ -29,4 +29,17 @@ Reserved Notation "\cat_ ( i < n | P ) F" ...@@ -29,4 +29,17 @@ Reserved Notation "\cat_ ( i < n | P ) F"
Notation "\cat_ ( i < n | P ) F" := Notation "\cat_ ( i < n | P ) F" :=
(\big[cat/[::]]_(i < n | P) F%N) : nat_scope. (\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.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment