Built with Alectryon, running Coq+SerAPI v8.15.0+0.15.0. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use instead of Ctrl.
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "_ + _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ - _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ <= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ < _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ >= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ > _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ <= _ <= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ < _ <= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ <= _ < _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ < _ < _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ * _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
(** * Service *) (** In this file, we establish basic facts about the service received by jobs. *) (** To begin with, we provide some simple but handy rewriting rules for [service] and [service_during]. *) Section Composition. (** Consider any job type and any processor state. *) Context {Job: JobType}. Context {PState: ProcessorState Job}. (** For any given schedule... *) Variable sched: schedule PState. (** ...and any given job... *) Variable j: Job. (** ...we establish a number of useful rewriting rules that decompose the service received during an interval into smaller intervals. *) (** As a trivial base case, no job receives any service during an empty interval. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t2 <= t1 -> service_during sched j t1 t2 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t2 <= t1 -> service_during sched j t1 t2 = 0
by move=> ? ? ?; rewrite /service_during big_geq. Qed. (** Equally trivially, no job has received service prior to time zero. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

service sched j 0 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

service sched j 0 = 0
by rewrite /service service_during_geq. Qed. (** Trivially, an interval consisting of one time unit is equivalent to [service_at]. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, service_during sched j t t.+1 = service_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, service_during sched j t t.+1 = service_at sched j t
by move=> ?; rewrite /service_during big_nat_recr// big_geq. Qed. (** Next, we observe that we can look at the service received during an interval <<[t1, t3)>> as the sum of the service during [t1, t2) and [t2, t3) for any t2 \in [t1, t3]. (The "_cat" suffix denotes the concatenation of the two intervals.) *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 t3 : nat, t1 <= t2 <= t3 -> service_during sched j t1 t2 + service_during sched j t2 t3 = service_during sched j t1 t3
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 t3 : nat, t1 <= t2 <= t3 -> service_during sched j t1 t2 + service_during sched j t2 t3 = service_during sched j t1 t3
by move => ? ? ? /andP[? ?]; rewrite -big_cat_nat. Qed. (** Since [service] is just a special case of [service_during], the same holds for [service]. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 <= t2 -> service sched j t1 + service_during sched j t1 t2 = service sched j t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 <= t2 -> service sched j t1 + service_during sched j t1 t2 = service sched j t2
move=> ? ? ?; exact: service_during_cat. Qed. (** As a special case, we observe that the service during an interval can be decomposed into the first instant and the rest of the interval. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 < t2 -> service_at sched j t1 + service_during sched j t1.+1 t2 = service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 < t2 -> service_at sched j t1 + service_during sched j t1.+1 t2 = service_during sched j t1 t2
by move=> ? ? ?; rewrite -service_during_instant service_during_cat// leqnSn. Qed. (** Symmetrically, we have the same for the end of the interval. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 <= t2 -> service_during sched j t1 t2 + service_at sched j t2 = service_during sched j t1 t2.+1
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 <= t2 -> service_during sched j t1 t2 + service_at sched j t2 = service_during sched j t1 t2.+1
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: nat
_Hyp_: t1 <= t2

service_during sched j t1 t2 + service_at sched j t2 = service_during sched j t1 t2 + service_during sched j t2 t2.+1
by rewrite service_during_instant. Qed. (** And hence also for [service]. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, service sched j t + service_at sched j t = service sched j t.+1
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, service sched j t + service_at sched j t = service sched j t.+1
move=> ?; exact: service_during_last_plus_before. Qed. (** Finally, we deconstruct the service received during an interval <<[t1, t3)>> into the service at a midpoint t2 and the service in the intervals before and after. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 t3 : nat, t1 <= t2 < t3 -> service_during sched j t1 t2 + service_at sched j t2 + service_during sched j t2.+1 t3 = service_during sched j t1 t3
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 t3 : nat, t1 <= t2 < t3 -> service_during sched j t1 t2 + service_at sched j t2 + service_during sched j t2.+1 t3 = service_during sched j t1 t3
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2, t3: nat
t1t2: t1 <= t2
t2t3: t2 < t3

service_during sched j t1 t2 + service_at sched j t2 + service_during sched j t2.+1 t3 = service_during sched j t1 t3
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2, t3: nat
t1t2: t1 <= t2
t2t3: t2 < t3

t1 <= t2 <= t3
by rewrite t1t2 ltnW. Qed. End Composition. (** As a common special case, we establish facts about schedules in which a job receives either 1 or 0 service units at all times. *) Section UnitService. (** Consider any job type and any processor state. *) Context {Job : JobType}. Context {PState : ProcessorState Job}. (** Let's consider a unit-service model... *) Hypothesis H_unit_service: unit_service_proc_model PState. (** ...and a given schedule. *) Variable sched : schedule PState. (** Let [j] be any job that is to be scheduled. *) Variable j : Job. (** First, we prove that the instantaneous service cannot be greater than 1, ... *)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall t : instant, service_at sched j t <= 1
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall t : instant, service_at sched j t <= 1
by rewrite /service_at. Qed. (** ... which implies that the instantaneous service always equals to 0 or 1. *)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall t : instant, service_at sched j t = 0 \/ service_at sched j t = 1
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall t : instant, service_at sched j t = 0 \/ service_at sched j t = 1
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job
t: instant

service_at sched j t = 0 \/ service_at sched j t = 1
by case: service_at (service_at_most_one t) => [|[|//]] _; [left|right]. Qed. (** Next we prove that the cumulative service received by job [j] in any interval of length [delta] is at most [delta]. *)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall (t : instant) (delta : nat), service_during sched j t (t + delta) <= delta
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall (t : instant) (delta : nat), service_during sched j t (t + delta) <= delta
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job
t: instant
delta: nat

service_during sched j t (t + delta) <= \sum_(t <= x < t + delta) 1
apply: leq_sum => t' _; exact: service_at_most_one. Qed. (** Conversely, we prove that if the cumulative service received by job [j] in an interval of length [delta] is greater than or equal to [ρ], then [ρ ≤ delta]. *)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall (t : instant) (delta ρ : nat), ρ <= service_during sched j t (t + delta) -> ρ <= delta
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

forall (t : instant) (delta ρ : nat), ρ <= service_during sched j t (t + delta) -> ρ <= delta
move=> ??? /leq_trans; apply; exact: cumulative_service_le_delta. Qed. Section ServiceIsUnitGrowthFunction. (** We show that the service received by any job [j] is a unit growth function. *)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

unit_growth_function (service sched j)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job

unit_growth_function (service sched j)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job
t: nat

service_at sched j t <= 1
exact: service_at_most_one. Qed. (** Next, consider any time [t]... *) Variable t : instant. (** ...and let [s] be any value less than the service received by job [j] by time [t]. *) Variable s : duration. Hypothesis H_less_than_s: s < service sched j t. (** Then, we show that there exists an earlier time [t'] where job [j] had [s] units of service. *)
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job
t: instant
s: duration
H_less_than_s: s < service sched j t

exists t' : nat, t' < t /\ service sched j t' = s
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job
t: instant
s: duration
H_less_than_s: s < service sched j t

exists t' : nat, t' < t /\ service sched j t' = s
Job: JobType
PState: ProcessorState Job
H_unit_service: unit_service_proc_model PState
sched: schedule PState
j: Job
t: instant
s: duration
H_less_than_s: s < service sched j t

service sched j 0 <= s < service sched j t
by rewrite service0. Qed. End ServiceIsUnitGrowthFunction. End UnitService. (** We establish a basic fact about the monotonicity of service. *) Section Monotonicity. (** Consider any job type and any processor model. *) Context {Job: JobType}. Context {PState: ProcessorState Job}. (** Consider any given schedule... *) Variable sched: schedule PState. (** ...and a given job that is to be scheduled. *) Variable j: Job. (** We observe that the amount of service received is monotonic by definition. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 <= t2 -> service sched j t1 <= service sched j t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : nat, t1 <= t2 -> service sched j t1 <= service sched j t2
by move=> t1 t2 ?; rewrite -(service_cat _ _ t1 t2)// leq_addr. Qed. End Monotonicity. (** Consider any job type and any processor model. *) Section RelationToScheduled. Context {Job: JobType}. Context {PState: ProcessorState Job}. (** Consider any given schedule... *) Variable sched: schedule PState. (** ...and a given job that is to be scheduled. *) Variable j: Job. (** We observe that a job that isn't scheduled in a given processor state cannot possibly receive service in that state. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall s : PState, ~~ scheduled_in j s -> service_in j s = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall s : PState, ~~ scheduled_in j s -> service_in j s = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
s: PState

~~ scheduled_in j s -> service_in j s = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
s: PState
Hsched: ~ (exists x : Core, scheduled_on j s x)
c: Core

true ==> (service_on j s c == 0)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
s: PState
Hsched: ~ (exists x : Core, scheduled_on j s x)
c: Core

~~ scheduled_on j s c
by apply/negP => ?; apply: Hsched; exists c. Qed. (** In particular, it cannot receive service at any given time. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, ~~ scheduled_at sched j t -> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, ~~ scheduled_at sched j t -> service_at sched j t = 0
move=> ?; exact: service_in_implies_scheduled_in. Qed. (** Conversely, if a job receives service, then it must be scheduled. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, 0 < service_at sched j t -> scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, 0 < service_at sched j t -> scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t: instant
SCHEDULED: scheduled_at sched j t = false

0 < service_at sched j t -> false
by rewrite not_scheduled_implies_no_service// negbT. Qed. (** Thus, if the cumulative amount of service changes, then it must be scheduled, too. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, service sched j t < service sched j t.+1 -> scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, service sched j t < service sched j t.+1 -> scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t: instant

0 < service_at sched j t -> scheduled_at sched j t
exact: service_at_implies_scheduled_at. Qed. (** We observe that a job receives cumulative service during some interval iff it receives services at some specific time in the interval. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : instant, 0 < service_during sched j t1 t2 <-> (exists t : nat, t1 <= t < t2 /\ 0 < service_at sched j t)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : instant, 0 < service_during sched j t1 t2 <-> (exists t : nat, t1 <= t < t2 /\ 0 < service_at sched j t)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant

0 < service_during sched j t1 t2 <-> (exists t : nat, t1 <= t < t2 /\ 0 < service_at sched j t)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant

0 < service_during sched j t1 t2 -> exists t : nat, t1 <= t < t2 /\ 0 < service_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t: nat
titv: t1 <= t < t2
nz_serv: 0 < service_at sched j t
0 < service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant

0 < service_during sched j t1 t2 -> exists t : nat, t1 <= t < t2 /\ 0 < service_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t: nat
titv: t1 <= t < t2
nz_serv: 0 < service_at sched j t
0 < service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t: nat_eqType
IN: t \in index_iota t1 t2
GT0: 0 < service_at sched j t

exists t : nat, t1 <= t < t2 /\ 0 < service_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t: nat
titv: t1 <= t < t2
nz_serv: 0 < service_at sched j t
0 < service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t: nat
titv: t1 <= t < t2
nz_serv: 0 < service_at sched j t

0 < service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t: nat
titv: t1 <= t < t2
nz_serv: 0 < service_at sched j t

0 < service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t: nat
titv: t1 <= t < t2
nz_serv: 0 < service_at sched j t

exists2 x : nat_eqType, x \in [seq _ <- index_iota t1 t2 | true] & 0 < service_at sched j x
by exists t; [rewrite filter_predT mem_index_iota|]. Qed. (** Thus, any job that receives some service during an interval must be scheduled at some point during the interval... *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : instant, 0 < service_during sched j t1 t2 -> exists t : nat, t1 <= t < t2 /\ scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t1 t2 : instant, 0 < service_during sched j t1 t2 -> exists t : nat, t1 <= t < t2 /\ scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
t': nat
TIMES: t1 <= t' < t2
SERVICED: 0 < service_at sched j t'

exists t : nat, t1 <= t < t2 /\ scheduled_at sched j t
exists t'; split=> //; exact: service_at_implies_scheduled_at. Qed. (** ...which implies that any job with positive cumulative service must have been scheduled at some point. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, 0 < service sched j t -> exists t' : nat, t' < t /\ scheduled_at sched j t'
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job

forall t : instant, 0 < service sched j t -> exists t' : nat, t' < t /\ scheduled_at sched j t'
by move=> t /cumulative_service_implies_scheduled[t' ?]; exists t'. Qed. (** If we can assume that a scheduled job always receives service, we can further prove the converse. *) Section GuaranteedService. (** Assume [j] always receives some positive service. *) Hypothesis H_scheduled_implies_serviced: ideal_progress_proc_model PState. (** In other words, not being scheduled is equivalent to receiving zero service. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t : instant, ~~ scheduled_at sched j t <-> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t : instant, ~~ scheduled_at sched j t <-> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState
t: instant

~~ scheduled_at sched j t <-> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState
t: instant
NO_SERVICE: service_at sched j t = 0

~~ scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState
t: instant
NO_SERVICE: service_at sched j t = 0

~~ (0 < service_in j (sched t))
by rewrite -eqn0Ngt -NO_SERVICE. Qed. (** Then, if a job does not receive any service during an interval, it is not scheduled. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t1 t2 : instant, service_during sched j t1 t2 = 0 -> forall t : nat, t1 <= t < t2 -> ~~ scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t1 t2 : instant, service_during sched j t1 t2 = 0 -> forall t : nat, t1 <= t < t2 -> ~~ scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState
t1, t2: instant

service_during sched j t1 t2 = 0 -> forall t : nat, t1 <= t < t2 -> ~~ scheduled_at sched j t
by move=> + t titv; rewrite no_service_not_scheduled big_nat_eq0; apply. Qed. (** Conversely, if a job is not scheduled during an interval, then it does not receive any service in that interval *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t1 t2 : nat, (forall t : nat, t1 <= t < t2 -> ~~ scheduled_at sched j t) -> service_during sched j t1 t2 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t1 t2 : nat, (forall t : nat, t1 <= t < t2 -> ~~ scheduled_at sched j t) -> service_during sched j t1 t2 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState
t1, t2, t: nat
titv: t1 <= t < t2

~~ scheduled_at sched j t -> service_at sched j t = 0
by rewrite no_service_not_scheduled. Qed. (** If a job is scheduled at some point in an interval, it receives positive cumulative service during the interval... *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t1 t2 : nat, (exists t : nat, t1 <= t < t2 /\ scheduled_at sched j t) -> 0 < service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t1 t2 : nat, (exists t : nat, t1 <= t < t2 /\ scheduled_at sched j t) -> 0 < service_during sched j t1 t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState
t1, t2, t: nat
titv: t1 <= t < t2
sch: scheduled_at sched j t

exists t : nat, t1 <= t < t2 /\ 0 < service_at sched j t
exists t; split=> //; exact: H_scheduled_implies_serviced. Qed. (** ...which again applies to total service, too. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t : nat, (exists t' : nat, t' < t /\ scheduled_at sched j t') -> 0 < service sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState

forall t : nat, (exists t' : nat, t' < t /\ scheduled_at sched j t') -> 0 < service sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H_scheduled_implies_serviced: ideal_progress_proc_model PState
t: nat

(exists t' : nat, t' < t /\ scheduled_at sched j t') -> 0 < service sched j t
by move=> [t' ?]; apply: scheduled_implies_cumulative_service; exists t'. Qed. End GuaranteedService. (** Furthermore, if we know that jobs are not released early, then we can narrow the interval during which they must have been scheduled. *) Section AfterArrival. Context `{JobArrival Job}. (** Assume that jobs must arrive to execute. *) Hypothesis H_jobs_must_arrive: jobs_must_arrive_to_execute sched. (** We prove that any job with positive cumulative service at time [t] must have been scheduled some time since its arrival and before time [t]. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : instant, 0 < service sched j t -> exists t' : nat, job_arrival j <= t' < t /\ scheduled_at sched j t'
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : instant, 0 < service sched j t -> exists t' : nat, job_arrival j <= t' < t /\ scheduled_at sched j t'
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched
t: instant
t': nat
t't: t' < t
sch: scheduled_at sched j t'

exists t' : nat, job_arrival j <= t' < t /\ scheduled_at sched j t'
exists t'; split=> //; rewrite t't andbT; exact: H_jobs_must_arrive. Qed.
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : nat, t < job_arrival j -> ~~ scheduled_at sched j t
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : nat, t < job_arrival j -> ~~ scheduled_at sched j t
by move=> t ?; apply: (contra (H_jobs_must_arrive j t)); rewrite -ltnNge. Qed. (** We show that job [j] does not receive service at any time [t] prior to its arrival. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : nat, t < job_arrival j -> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : nat, t < job_arrival j -> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched
t: nat
NOT_ARR: t < job_arrival j

~~ scheduled_at sched j t
exact: not_scheduled_before_arrival. Qed. (** Note that the same property applies to the cumulative service. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t1 t2 : instant, t2 <= job_arrival j -> service_during sched j t1 t2 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t1 t2 : instant, t2 <= job_arrival j -> service_during sched j t1 t2 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched
t1, t2: instant
early: t2 <= job_arrival j
t: nat
t_lt_t2: t < t2

service_at sched j t = 0
apply: service_before_job_arrival_zero; exact: leq_trans early. Qed. (** Hence, one can ignore the service received by a job before its arrival time... *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t1 t2 : nat, t1 <= job_arrival j -> job_arrival j <= t2 -> service_during sched j t1 t2 = service_during sched j (job_arrival j) t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t1 t2 : nat, t1 <= job_arrival j -> job_arrival j <= t2 -> service_during sched j t1 t2 = service_during sched j (job_arrival j) t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched
t1, t2: nat
t1_le: t1 <= job_arrival j
t2_ge: job_arrival j <= t2

service_during sched j t1 t2 = service_during sched j (job_arrival j) t2
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched
t1, t2: nat
t1_le: t1 <= job_arrival j
t2_ge: job_arrival j <= t2

service_during sched j t1 (job_arrival j) + service_during sched j (job_arrival j) t2 = service_during sched j (job_arrival j) t2
by rewrite cumulative_service_before_job_arrival_zero. Qed. (** ... which we can also state in terms of cumulative service. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : nat, t <= job_arrival j -> service sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
H: JobArrival Job
H_jobs_must_arrive: jobs_must_arrive_to_execute sched

forall t : nat, t <= job_arrival j -> service sched j t = 0
exact: cumulative_service_before_job_arrival_zero. Qed. End AfterArrival. (** In this section, we prove some lemmas about time instants with same service. *) Section TimesWithSameService. (** Consider any time instants [t1] and [t2]... *) Variable t1 t2: instant. (** ...where [t1] is no later than [t2]... *) Hypothesis H_t1_le_t2: t1 <= t2. (** ...and where job [j] has received the same amount of service. *) Hypothesis H_same_service: service sched j t1 = service sched j t2. (** First, we observe that this means that the job receives no service during <<[t1, t2)>>... *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2

service_during sched j t1 t2 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2

service_during sched j t1 t2 = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2

service sched j t1 == service sched j t1 + service_during sched j t1 t2 -> service_during sched j t1 t2 = 0
by rewrite -[X in X == _]addn0 eqn_add2l => /eqP. Qed. (** ...which of course implies that it does not receive service at any point, either. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2

forall t : nat, t1 <= t < t2 -> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2

forall t : nat, t1 <= t < t2 -> service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: nat
titv: t1 <= t < t2

service_at sched j t = 0
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: nat
titv: t1 <= t < t2

service_during sched j t1 t2 = 0 -> service_at sched j t = 0
rewrite big_nat_eq0; exact. Qed. (** We show that job [j] receives service at some point [t < t1] iff [j] receives service at some point [t' < t2]. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2

[exists t, 0 < service_at sched j t] = [exists t', 0 < service_at sched j t']
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2

[exists t, 0 < service_at sched j t] = [exists t', 0 < service_at sched j t']
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t1
serv: 0 < service_at sched j t

[exists t', 0 < service_at sched j t']
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t2
serv: 0 < service_at sched j t
[exists t, 0 < service_at sched j t]
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t1
serv: 0 < service_at sched j t

[exists t', 0 < service_at sched j t']
by apply/existsP; exists (widen_ord H_t1_le_t2 t).
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t2
serv: 0 < service_at sched j t

[exists t, 0 < service_at sched j t]
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t2
serv: 0 < service_at sched j t
t_lt_t1: t < t1

[exists t, 0 < service_at sched j t]
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t2
serv: 0 < service_at sched j t
t1_le_t: t1 <= t
[exists t, 0 < service_at sched j t]
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t2
serv: 0 < service_at sched j t
t_lt_t1: t < t1

[exists t, 0 < service_at sched j t]
by apply/existsP; exists (Ordinal t_lt_t1).
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t2
serv: 0 < service_at sched j t
t1_le_t: t1 <= t

[exists t, 0 < service_at sched j t]
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
t: ordinal_finType t2
t1_le_t: t1 <= t

service_at sched j t == 0
by apply/eqP/constant_service_implies_not_scheduled; rewrite t1_le_t /=. Qed. (** Then, under the assumption that scheduled jobs receives service, we can translate this into a claim about scheduled_at. *) (** Assume [j] always receives some positive service. *) Hypothesis H_scheduled_implies_serviced: ideal_progress_proc_model PState. (** We show that job [j] is scheduled at some point [t < t1] iff [j] is scheduled at some point [t' < t2]. *)
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState

[exists t, scheduled_at sched j t] = [exists t', scheduled_at sched j t']
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState

[exists t, scheduled_at sched j t] = [exists t', scheduled_at sched j t']
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat

[exists b, scheduled_at sched j b] = [exists b, 0 < service_at sched j b]
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
CONV: forall B : nat, [exists b, scheduled_at sched j b] = [exists b, 0 < service_at sched j b]
[exists t, scheduled_at sched j t] = [exists t', scheduled_at sched j t']
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat

[exists b, scheduled_at sched j b] = [exists b, 0 < service_at sched j b]
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat
b: ordinal_finType B
P: scheduled_at sched j b

0 < service_at sched j b
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat
b: ordinal_finType B
P: 0 < service_at sched j b
scheduled_at sched j b
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat
b: ordinal_finType B
P: scheduled_at sched j b

0 < service_at sched j b
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat
b: ordinal_finType B
P: 0 < service_at sched j b
scheduled_at sched j b
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat
b: ordinal_finType B
P: 0 < service_at sched j b

scheduled_at sched j b
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
B: nat
b: ordinal_finType B
P: 0 < service_at sched j b

scheduled_at sched j b
exact: service_at_implies_scheduled_at.
Job: JobType
PState: ProcessorState Job
sched: schedule PState
j: Job
t1, t2: instant
H_t1_le_t2: t1 <= t2
H_same_service: service sched j t1 = service sched j t2
H_scheduled_implies_serviced: ideal_progress_proc_model PState
CONV: forall B : nat, [exists b, scheduled_at sched j b] = [exists b, 0 < service_at sched j b]

[exists t, scheduled_at sched j t] = [exists t', scheduled_at sched j t']
by rewrite !CONV same_service_implies_serviced_at_earlier_times. Qed. End TimesWithSameService. End RelationToScheduled. Section ServiceInTwoSchedules. (** Consider any job type and any processor model. *) Context {Job: JobType}. Context {PState: ProcessorState Job}. (** Consider any two given schedules... *) Variable sched1 sched2: schedule PState. (** Given an interval in which the schedules provide the same service to a job at each instant, we can prove that the cumulative service received during the interval has to be the same. *) Section ServiceDuringEquivalentInterval. (** Consider two time instants... *) Variable t1 t2 : instant. (** ...and a given job that is to be scheduled. *) Variable j: Job. (** Assume that, in any instant between [t1] and [t2] the service provided to [j] from the two schedules is the same. *) Hypothesis H_sched1_sched2_same_service_at: forall t, t1 <= t < t2 -> service_at sched1 j t = service_at sched2 j t. (** It follows that the service provided during [t1] and [t2] is also the same. *)
Job: JobType
PState: ProcessorState Job
sched1, sched2: schedule PState
t1, t2: instant
j: Job
H_sched1_sched2_same_service_at: forall t : nat, t1 <= t < t2 -> service_at sched1 j t = service_at sched2 j t

service_during sched1 j t1 t2 = service_during sched2 j t1 t2
Job: JobType
PState: ProcessorState Job
sched1, sched2: schedule PState
t1, t2: instant
j: Job
H_sched1_sched2_same_service_at: forall t : nat, t1 <= t < t2 -> service_at sched1 j t = service_at sched2 j t

service_during sched1 j t1 t2 = service_during sched2 j t1 t2
exact/eq_big_nat/H_sched1_sched2_same_service_at. Qed. End ServiceDuringEquivalentInterval. (** We can leverage the previous lemma to conclude that two schedules that match in a given interval will also have the same cumulative service across the interval. *)
Job: JobType
PState: ProcessorState Job
sched1, sched2: schedule PState

forall t1 t2 : nat, (forall t : nat, t1 <= t < t2 -> sched1 t = sched2 t) -> forall j : Job, service_during sched1 j t1 t2 = service_during sched2 j t1 t2
Job: JobType
PState: ProcessorState Job
sched1, sched2: schedule PState

forall t1 t2 : nat, (forall t : nat, t1 <= t < t2 -> sched1 t = sched2 t) -> forall j : Job, service_during sched1 j t1 t2 = service_during sched2 j t1 t2
Job: JobType
PState: ProcessorState Job
sched1, sched2: schedule PState
t1, t2: nat
sch: forall t : nat, t1 <= t < t2 -> sched1 t = sched2 t
j: Job
t': nat
t'itv: t1 <= t' < t2

service_at sched1 j t' = service_at sched2 j t'
by rewrite /service_at sch. Qed. (** For convenience, we restate the corollary also at the level of [service] for identical prefixes. *)
Job: JobType
PState: ProcessorState Job
sched1, sched2: schedule PState

forall h : instant, identical_prefix sched1 sched2 h -> forall j : Job, service sched1 j h = service sched2 j h
Job: JobType
PState: ProcessorState Job
sched1, sched2: schedule PState

forall h : instant, identical_prefix sched1 sched2 h -> forall j : Job, service sched1 j h = service sched2 j h
move=> ? ? ?; exact: equal_prefix_implies_same_service_during. Qed. End ServiceInTwoSchedules.