Commit 877d6625 authored by Vedant Chavda's avatar Vedant Chavda Committed by Björn Brandenburg

define a shifted job costs function and prove its validity

parent 137760b3
Pipeline #33769 passed with stages
in 18 minutes and 50 seconds
......@@ -5,29 +5,75 @@ From mathcomp Require Import div.
(** In this file we define the notion of a hyperperiod for periodic tasks. *)
Section Hyperperiod.
(** Consider periodic tasks. *)
(** Consider any type of periodic tasks ... *)
Context {Task : TaskType} `{PeriodicModel Task}.
(** Consider any task set [ts]... *)
(** ... and any task set [ts]. *)
Variable ts : TaskSet Task.
(** ... and any task [tsk] that belongs to this task set. *)
Variable tsk : Task.
Hypothesis H_tsk_in_ts : tsk \in ts.
(** The hyperperiod of a task set is defined as the least common multiple
(LCM) of the periods of all tasks in the task set. **)
(LCM) of the periods of all tasks in the task set. **)
Definition hyperperiod : duration := lcml (map task_period ts).
(** Consequently, a task set's hyperperiod is an integral multiple
of each task's period in the task set. **)
Lemma hyperperiod_int_mult_of_any_task :
exists k, hyperperiod = k * task_period tsk.
Proof.
apply lcm_seq_is_mult_of_all_ints.
apply map_f.
by apply H_tsk_in_ts.
Qed.
End Hyperperiod.
(** In this section we provide basic definitions concerning the hyperperiod
of all tasks in a task set. *)
Section HyperperiodDefinitions.
(** Consider any type of periodic tasks ... *)
Context {Task : TaskType}.
Context `{TaskOffset Task}.
Context `{PeriodicModel Task}.
(** ... and any type of jobs. *)
Context {Job : JobType}.
Context `{JobTask Job Task}.
Context `{JobArrival Job}.
(** Consider any task set [ts] ... *)
Variable ts : TaskSet Task.
(** ... and any arrival sequence [arr_seq]. *)
Variable arr_seq : arrival_sequence Job.
(** Let [O_max] denote the maximum offset of all tasks in [ts] ... *)
Let O_max := max_task_offset ts.
(** ... and let [HP] denote the hyperperiod of all tasks in [ts]. *)
Let HP := hyperperiod ts.
(** We define a hyperperiod index based on an instant [t]
which lies in it. *)
(** Note that we consider the first hyperperiod to start at time [O_max],
i.e., shifted by the maximum offset (and not at time zero as can also
be found sometimes in the literature) *)
Definition hyperperiod_index (t : instant) :=
(t - O_max) %/ HP.
(** Given an instant [t], we define the starting instant of the hyperperiod
that contains [t]. *)
Definition starting_instant_of_hyperperiod (t : instant) :=
hyperperiod_index t * HP + O_max.
(** Given a job [j], we define the starting instant of the hyperperiod
in which [j] arrives. *)
Definition starting_instant_of_corresponding_hyperperiod (j : Job) :=
starting_instant_of_hyperperiod (job_arrival j).
(** We define the sequence of jobs of a task [tsk] that arrive in a hyperperiod
given the starting instant [h] of the hyperperiod. *)
Definition jobs_in_hyperperiod (h : instant) (tsk : Task) :=
task_arrivals_between arr_seq tsk h (h + HP).
(** We define the index of a job [j] of task [tsk] in a hyperperiod starting at [h]. *)
Definition job_index_in_hyperperiod (j : Job) (h : instant) (tsk : Task) :=
index j (jobs_in_hyperperiod h tsk).
(** Given a job [j] of task [tsk] and the hyperperiod starting at [h], we define a
[corresponding_job_in_hyperperiod] which is the job that arrives in given hyperperiod
and has the same [job_index] as [j]. *)
Definition corresponding_job_in_hyperperiod (j : Job) (h : instant) (tsk : Task) :=
nth j (jobs_in_hyperperiod h tsk) (job_index_in_hyperperiod j (starting_instant_of_corresponding_hyperperiod j) tsk).
End HyperperiodDefinitions.
Require Export prosa.model.task.arrivals.
(** In this section we define the notion of an infinite release
of jobs by a task. *)
Section InfiniteJobs.
(** Consider any type of tasks ... *)
Context {Task : TaskType}.
(** ... and any type of jobs associated with these tasks. *)
Context {Job : JobType}.
Context `{JobTask Job Task}.
Context `{JobArrival Job}.
(** Consider any arrival sequence. *)
Variable arr_seq : arrival_sequence Job.
(** We say that a task [tsk] releases an infinite number of jobs
if for every integer [n] there exists a job [j] of task [tsk]
such that [job_index] of [j] is equal to [n]. *)
Definition infinite_jobs :=
forall tsk n,
exists j,
arrives_in arr_seq j /\
job_task j = tsk /\
job_index arr_seq j = n.
End InfiniteJobs.
Require Export prosa.behavior.all.
(** In this section we define what it means for the response time
of a job to exceed some given duration. *)
Section JobResponseTimeExceeds.
(** Consider any kind of jobs ... *)
Context {Job : JobType}.
Context `{JobCost Job}.
Context `{JobArrival Job}.
(** ... and any kind of processor state. *)
Context `{PState : Type}.
Context `{ProcessorState Job PState}.
(** Consider any schedule. *)
Variable sched : schedule PState.
(** We say that a job [j] has a response time exceeding a number [x]
if [j] is pending [x] units of time after its arrival. *)
Definition job_response_time_exceeds (j : Job) (x : duration) :=
~~ completed_by sched j ((job_arrival j) + x).
End JobResponseTimeExceeds.
This diff is collapsed.
Require Export prosa.model.task.offset.
Require Export prosa.analysis.facts.job_index.
(** In this module, we'll prove a property of task offsets. *)
(** In this module, we prove some properties of task offsets. *)
Section OffsetLemmas.
(** Consider any type of tasks with an offset ... *)
......@@ -13,12 +13,13 @@ Section OffsetLemmas.
Context `{JobTask Job Task}.
Context `{JobArrival Job}.
(** Consider any arrival sequence with consistent and non-duplicate arrivals, ... *)
(** Consider any arrival sequence with consistent and non-duplicate arrivals ... *)
Variable arr_seq : arrival_sequence Job.
Hypothesis H_consistent_arrivals: consistent_arrival_times arr_seq.
Hypothesis H_uniq_arr_seq: arrival_sequence_uniq arr_seq.
(** ... and any job [j] of any task [tsk] with a valid offset. *)
(** ... and any job [j] (that stems from the arrival sequence) of any
task [tsk] with a valid offset. *)
Variable tsk : Task.
Variable j : Job.
Hypothesis H_job_of_task: job_task j = tsk.
......@@ -43,5 +44,20 @@ Section OffsetLemmas.
now apply/eqP; rewrite eqn_leq; apply/andP; split;
[ssrlia | apply H_valid_offset].
Qed.
(** Consider any task set [ts]. *)
Variable ts : TaskSet Task.
(** If task [tsk] is in [ts], then its offset
is less than or equal to the maximum offset of all tasks
in [ts]. *)
Lemma max_offset_g:
tsk \in ts ->
task_offset tsk <= max_task_offset ts.
Proof.
intros TSK_IN.
apply in_max0_le.
now apply map_f.
Qed.
End OffsetLemmas.
......@@ -13,7 +13,7 @@ Section TaskArrivals.
(** Consider any job arrival sequence with consistent arrivals. *)
Variable arr_seq : arrival_sequence Job.
Hypothesis H_consistent_arrivals : consistent_arrival_times arr_seq.
Hypothesis H_consistent_arrivals: consistent_arrival_times arr_seq.
(** We show that the number of arrivals of task can be split into disjoint intervals. *)
Lemma num_arrivals_of_task_cat:
......@@ -133,19 +133,30 @@ Section TaskArrivals.
now apply arrived_between_implies_in_arrivals.
Qed.
(** Any job [j] in [task_arrivals_between arr_seq tsk t1 t2] arrives
in the arrival sequence [arr_seq]. *)
Lemma arrives_in_task_arrivals_implies_arrived:
forall t1 t2 j,
j \in (task_arrivals_between arr_seq tsk t1 t2) ->
arrives_in arr_seq j.
Proof.
intros * JB_IN.
move : JB_IN; rewrite mem_filter; move => /andP [/eqP TSK JB_IN].
now apply in_arrivals_implies_arrived in JB_IN.
Qed.
(** An arrival sequence with non-duplicate arrivals implies that the
task arrivals also contain non-duplicate arrivals. *)
Lemma uniq_task_arrivals:
forall j,
arrives_in arr_seq j ->
forall t,
arrival_sequence_uniq arr_seq ->
uniq (task_arrivals_up_to arr_seq (job_task j) (job_arrival j)).
uniq (task_arrivals_up_to arr_seq tsk t).
Proof.
intros j ARR UNQ_ARR.
intros * UNQ_SEQ.
apply filter_uniq.
now apply arrivals_uniq.
Qed.
(** A job cannot arrive before it's arrival time. *)
Lemma job_notin_task_arrivals_before:
forall j t,
......@@ -180,5 +191,58 @@ Section TaskArrivals.
- rewrite /task_arrivals_up_to_job_arrival TSK1 TSK2.
now rewrite -task_arrivals_cat; try by ssrlia.
Qed.
(** For any job [j2] with [job_index] equal to [n], the nth job
in the sequence [task_arrivals_up_to arr_seq tsk t] is [j2], given that
[t] is not less than [job_arrival j2]. *)
(** Note that [j_def] is used as a default job for the access function and
has nothing to do with the lemma. *)
Lemma nth_job_of_task_arrivals:
forall n j_def j t,
arrives_in arr_seq j ->
job_task j = tsk ->
job_index arr_seq j = n ->
t >= job_arrival j ->
nth j_def (task_arrivals_up_to arr_seq tsk t) n = j.
Proof.
intros * ARR TSK IND T_G.
rewrite -IND.
have EQ_IND : index j (task_arrivals_up_to_job_arrival arr_seq j) = index j (task_arrivals_up_to arr_seq tsk t).
{ have CAT : exists xs, task_arrivals_up_to_job_arrival arr_seq j ++ xs = task_arrivals_up_to arr_seq tsk t.
{ rewrite /task_arrivals_up_to_job_arrival TSK.
exists (task_arrivals_between arr_seq tsk ((job_arrival j).+1) t.+1).
now rewrite -task_arrivals_cat.
}
move : CAT => [xs ARR_CAT].
now rewrite -ARR_CAT index_cat ifT; last by apply arrives_in_task_arrivals_up_to.
}
rewrite /job_index EQ_IND nth_index => //.
rewrite mem_filter; apply /andP.
split; first by apply /eqP.
now apply job_in_arrivals_between => //.
Qed.
(** We show that task arrivals in the interval <<[t1, t2)>>
is the same as concatenation of task arrivals at each instant in <<[t1, t2)>>. *)
Lemma task_arrivals_between_is_cat_of_task_arrivals_at:
forall t1 t2,
task_arrivals_between arr_seq tsk t1 t2 = \cat_(t1 <= t < t2) task_arrivals_at arr_seq tsk t.
Proof.
intros *.
rewrite /task_arrivals_between /task_arrivals_at /arrivals_between.
now apply cat_filter_eq_filter_cat.
Qed.
(** The number of jobs of a task [tsk] in the interval <<[t1, t2)>> is the same
as sum of the number of jobs of the task [tsk] at each instant in <<[t1, t2)>>. *)
Lemma size_of_task_arrivals_between:
forall t1 t2,
size (task_arrivals_between arr_seq tsk t1 t2)
= \sum_(t1 <= t < t2) size (task_arrivals_at arr_seq tsk t).
Proof.
intros *.
rewrite /task_arrivals_between /task_arrivals_at /arrivals_between.
now rewrite size_big_nat cat_filter_eq_filter_cat.
Qed.
End TaskArrivals.
......@@ -49,5 +49,47 @@ Section PeriodicArrivalTimes.
rewrite ARRIVAL IHn; ssrlia.
}
Qed.
(** We show that for every job [j] of task [tsk] there exists a number
[n] such that [j] arrives at the instant [task_offset tsk + n * task_period tsk]. *)
Lemma job_arrival_times:
forall j,
arrives_in arr_seq j ->
job_task j = tsk ->
exists n, job_arrival j = task_offset tsk + n * task_period tsk.
Proof.
intros * ARR TSK.
exists (job_index arr_seq j).
specialize (periodic_arrival_times (job_index arr_seq j) j) => J_ARR.
now feed_n 3 J_ARR => //.
Qed.
(** If a job [j] of task [tsk] arrives at [task_offset tsk + n * task_period tsk]
then the [job_index] of [j] is equal to [n]. *)
Lemma job_arr_index:
forall n j,
arrives_in arr_seq j ->
job_task j = tsk ->
job_arrival j = task_offset tsk + n * task_period tsk ->
job_index arr_seq j = n.
Proof.
have F : task_period tsk > 0 by auto.
induction n.
+ intros * ARR_J TSK ARR.
destruct (PeanoNat.Nat.zero_or_succ (job_index arr_seq j)) as [Z | [m SUCC]] => //.
now apply periodic_arrival_times in SUCC => //; ssrlia.
+ intros * ARR_J TSK ARR.
specialize (H_task_respects_periodic_model j); feed_n 3 H_task_respects_periodic_model => //.
{ rewrite lt0n; apply /eqP; intro EQ.
apply first_job_arrival with (tsk0 := tsk) in EQ => //.
now rewrite EQ in ARR; ssrlia.
}
move : H_task_respects_periodic_model => [j' [ARR' [IND' [TSK' [ARRIVAL']]]]].
specialize (IHn j'); feed_n 3 IHn => //; first by rewrite ARR in ARRIVAL'; ssrlia.
rewrite IHn in IND'.
destruct (PeanoNat.Nat.zero_or_succ (job_index arr_seq j)) as [Z | [m SUCC]]; last by ssrlia.
apply first_job_arrival with (tsk0 := tsk) in Z => //.
now rewrite Z in ARR; ssrlia.
Qed.
End PeriodicArrivalTimes.
Require Export prosa.analysis.facts.periodic.arrival_times.
Require Export prosa.analysis.definitions.infinite_jobs.
(** In this file we prove some properties concerning the size
of task arrivals in context of the periodic model. *)
Section TaskArrivalsSize.
(** Consider any type of periodic tasks with an offset ... *)
Context {Task : TaskType}.
Context `{TaskOffset Task}.
Context `{PeriodicModel Task}.
(** ... and any type of jobs associated with these tasks. *)
Context {Job : JobType}.
Context `{JobTask Job Task}.
Context `{JobArrival Job}.
(** Consider any unique arrival sequence with consistent arrivals ... *)
Variable arr_seq : arrival_sequence Job.
Hypothesis H_consistent_arrivals: consistent_arrival_times arr_seq.
Hypothesis H_uniq_arr_seq: arrival_sequence_uniq arr_seq.
(** ... and any periodic task [tsk] with a valid offset and period. *)
Variable tsk : Task.
Hypothesis H_valid_offset: valid_offset arr_seq tsk.
Hypothesis H_valid_period: valid_period tsk.
Hypothesis H_task_respects_periodic_model: respects_periodic_task_model arr_seq tsk.
(** We show that if an instant [t] is not an "arrival time" for
task [tsk] then [task_arrivals_at arr_seq tsk t] is an empty sequence. *)
Lemma task_arrivals_size_at_non_arrival:
forall t,
(forall n, t <> task_offset tsk + n * task_period tsk) ->
task_arrivals_at arr_seq tsk t = [::].
Proof.
intros * T.
have EMPT_OR_EXISTS : forall xs, xs = [::] \/ exists a, a \in xs.
{ intros *.
induction xs; first by left.
right; exists a.
now apply mem_head.
}
destruct (EMPT_OR_EXISTS Job (task_arrivals_at arr_seq tsk t)) as [EMPT | [a A_IN]] => //.
rewrite /task_arrivals_at mem_filter in A_IN; move : A_IN => /andP [/eqP TSK A_ARR].
move : (A_ARR) => A_IN; apply H_consistent_arrivals in A_IN.
rewrite -A_IN in T; rewrite /arrivals_at in A_ARR.
apply in_arrseq_implies_arrives in A_ARR.
have EXISTS_N : exists n, job_arrival a = task_offset tsk + n * task_period tsk by
apply job_arrival_times with (arr_seq0 := arr_seq) => //.
move : EXISTS_N => [n A_ARRIVAL].
now move : (T n) => T1.
Qed.
(** We show that at any instant [t], at most one job of task [tsk]
can arrive (i.e. size of [task_arrivals_at arr_seq tsk t] is at most one). *)
Lemma task_arrivals_at_size_cases:
forall t,
size (task_arrivals_at arr_seq tsk t) = 0 \/
size (task_arrivals_at arr_seq tsk t) = 1.
Proof.
intro t.
case: (ltngtP (size (task_arrivals_at arr_seq tsk t)) 1) => [LT|GT|EQ]; try by auto.
destruct (size (task_arrivals_at arr_seq tsk t)); now left.
specialize (exists_two Job (task_arrivals_at arr_seq tsk t)) => EXISTS_TWO.
destruct EXISTS_TWO as [a [b [NEQ [A_IN B_IN]]]]; [by done | by apply filter_uniq | ].
rewrite mem_filter in A_IN; rewrite mem_filter in B_IN.
move: A_IN B_IN => /andP [/eqP TSKA ARRA] /andP [/eqP TSKB ARRB].
move: (ARRA); move: (ARRB); rewrite /arrivals_at => A_IN B_IN.
apply in_arrseq_implies_arrives in A_IN; apply in_arrseq_implies_arrives in B_IN.
have SPO : respects_sporadic_task_model arr_seq tsk; try by auto with basic_facts.
have EQ_ARR_A : (job_arrival a = t) by apply H_consistent_arrivals.
have EQ_ARR_B : (job_arrival b = t) by apply H_consistent_arrivals.
specialize (SPO a b); feed_n 6 SPO => //; try by ssrlia.
rewrite EQ_ARR_A EQ_ARR_B in SPO.
rewrite /task_min_inter_arrival_time /periodic_as_sporadic in SPO.
have POS : task_period tsk > 0 by auto.
now ssrlia.
Qed.
(** We show that the size of task arrivals (strictly) between two consecutive arrival
times is zero. *)
Lemma size_task_arrivals_between_eq0:
forall n,
let l := (task_offset tsk + n * task_period tsk).+1 in
let r := (task_offset tsk + n.+1 * task_period tsk) in
size (task_arrivals_between arr_seq tsk l r) = 0.
Proof.
intros n l r; rewrite /l /r.
rewrite size_of_task_arrivals_between big_nat_eq0 => //; intros t INEQ.
rewrite task_arrivals_size_at_non_arrival => //; intros n1 EQ.
rewrite EQ in INEQ.
move : INEQ => /andP [INEQ1 INEQ2].
rewrite ltn_add2l ltn_mul2r in INEQ1; rewrite ltn_add2l ltn_mul2r in INEQ2.
move : INEQ1 INEQ2 => /andP [A B] /andP [C D].
now ssrlia.
Qed.
(** In this section we show some properties of task arrivals in case
of an infinite sequence of jobs. *)
Section TaskArrivalsInCaseOfInfiniteJobs.
(** Assume that we have an infinite sequence of jobs. *)
Hypothesis H_infinite_jobs: infinite_jobs arr_seq.
(** We show that for any number [n], there exists a job [j] of task [tsk]
such that [job_index] of [j] is equal to [n] and [j] arrives
at [task_offset tsk + n * task_period tsk]. *)
Lemma jobs_exists_later:
forall n,
exists j,
arrives_in arr_seq j /\
job_task j = tsk /\
job_arrival j = task_offset tsk + n * task_period tsk /\
job_index arr_seq j = n.
Proof.
intros *.
destruct (H_infinite_jobs tsk n) as [j [ARR [TSK IND]]].
exists j; repeat split => //.
now apply periodic_arrival_times with (arr_seq0 := arr_seq) => //.
Qed.
(** We show that the size of task arrivals at any arrival time is equal to one. *)
Lemma task_arrivals_at_size:
forall n,
let l := (task_offset tsk + n * task_period tsk) in
size (task_arrivals_at arr_seq tsk l) = 1.
Proof.
intros n l; rewrite /l.
move : (jobs_exists_later n) => [j' [ARR [TSK [ARRIVAL IND]]]].
apply only_j_in_task_arrivals_at_j with (tsk0 := tsk) in ARR => //; last by
auto with basic_facts.
rewrite /task_arrivals_at_job_arrival TSK in ARR.
now rewrite -ARRIVAL ARR.
Qed.
(** We show that the size of task arrivals up to [task_offset tsk] is equal to one. *)
Lemma size_task_arrivals_up_to_offset:
size (task_arrivals_up_to arr_seq tsk (task_offset tsk)) = 1.
Proof.
rewrite /task_arrivals_up_to.
specialize (task_arrivals_between_cat arr_seq tsk 0 (task_offset tsk) (task_offset tsk).+1) => CAT.
feed_n 2 CAT => //; rewrite CAT size_cat.
have Z : size (task_arrivals_between arr_seq tsk 0 (task_offset tsk)) = 0.
{ rewrite size_of_task_arrivals_between big_nat_eq0 => //; intros t T_EQ.
rewrite task_arrivals_size_at_non_arrival => //; intros n EQ.
now ssrlia.
}
rewrite Z add0n /task_arrivals_between /arrivals_between big_nat1.
specialize (task_arrivals_at_size 0) => AT_SIZE.
now rewrite mul0n addn0 in AT_SIZE.
Qed.
(** We show that for any number [n], the number of jobs released by task [tsk] up to
[task_offset tsk + n * task_period tsk] is equal to [n + 1]. *)
Lemma task_arrivals_up_to_size:
forall n,
let l := (task_offset tsk + n * task_period tsk) in
let r := (task_offset tsk + n.+1 * task_period tsk) in
size (task_arrivals_up_to arr_seq tsk l) = n + 1.
Proof.
induction n.
intros l r; rewrite /l mul0n add0n addn0.
now apply size_task_arrivals_up_to_offset.
intros l r.
specialize (task_arrivals_cat arr_seq tsk (task_offset tsk + n * task_period tsk)
(task_offset tsk + n.+1 * task_period tsk)) => CAT.
feed_n 1 CAT; first by ssrlia.
rewrite CAT size_cat IHn.
specialize (task_arrivals_between_cat arr_seq tsk (task_offset tsk + n * task_period tsk).+1
(task_offset tsk + n.+1 * task_period tsk) (task_offset tsk + n.+1 * task_period tsk).+1) => S_CAT.
feed_n 2 S_CAT; try by ssrlia.
{ rewrite ltn_add2l ltn_mul2r.
now apply /andP; split => //.
}
rewrite S_CAT size_cat /task_arrivals_between /arrivals_between big_nat1.
rewrite size_task_arrivals_between_eq0 task_arrivals_at_size => //.
now ssrlia.
Qed.
(** We show that the number of jobs released by task [tsk] at any instant [t]
and [t + n * task_period tsk] is the same for any number [n]. *)
Lemma eq_size_of_task_arrivals_seperated_by_period:
forall n t,
t >= task_offset tsk ->
size (task_arrivals_at arr_seq tsk t) =
size (task_arrivals_at arr_seq tsk (t + n * task_period tsk)).
Proof.
intros * T_G.
destruct (exists_or_not_add_mul_cases (task_offset tsk) (task_period tsk) t) as [[n1 JB_ARR] | JB_NOT_ARR].
+ have EXISTS_N : exists nn, t + n * task_period tsk = task_offset tsk + nn * task_period tsk.
{ exists (n1 + n).
now rewrite JB_ARR; ssrlia.
}
move : EXISTS_N => [nn JB_ARR'].
now rewrite JB_ARR' JB_ARR !task_arrivals_at_size => //.
+ have FORALL_N : forall nn, t + n * task_period tsk <> task_offset tsk + nn * task_period tsk by apply mul_add_neq.
now rewrite !task_arrivals_size_at_non_arrival.
Qed.
End TaskArrivalsInCaseOfInfiniteJobs.
End TaskArrivalsSize.
Require Export prosa.analysis.facts.periodic.arrival_times.
Require Export prosa.analysis.facts.periodic.task_arrivals_size.
Require Export prosa.model.task.concept.
Require Export prosa.analysis.facts.hyperperiod.
(** In this file we define a new function for job costs
in an observation interval and prove its validity. *)
Section ValidJobCostsShifted.
(** Consider any type of periodic tasks ... *)
Context {Task : TaskType}.
Context `{TaskOffset Task}.
Context `{PeriodicModel Task}.
Context `{TaskCost Task}.
(** ... and any type of jobs. *)
Context {Job : JobType}.
Context `{JobTask Job Task}.
Context `{JobArrival Job}.
Context `{JobCost Job}.
Context `{JobDeadline Job}.
(** Consider a consistent arrival sequence with non-duplicate arrivals. *)
Variable arr_seq : arrival_sequence Job.
Hypothesis H_consistent_arrivals: consistent_arrival_times arr_seq.
Hypothesis H_uniq_arr_seq: arrival_sequence_uniq arr_seq.
(** Furthermore, assume that arrivals have valid job costs. *)
Hypothesis H_arrivals_have_valid_job_costs: arrivals_have_valid_job_costs arr_seq.
(** Consider a periodic task set [ts] such that all tasks in
[ts] have valid periods and offsets. *)
Variable ts : TaskSet Task.
Hypothesis H_periodic_taskset: taskset_respects_periodic_task_model arr_seq ts.
Hypothesis H_valid_periods_in_taskset: valid_periods ts.