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]
(** * Lemmas about Workload of Sets of Jobs *) (** In this file, we establish basic facts about the workload of sets of jobs. *) Section WorkloadFacts. (** Consider any type of tasks ... *) Context {Task : TaskType}. Context `{TaskCost Task}. (** ... and any type of jobs associated with these tasks. *) Context {Job : JobType}. Context `{JobTask Job Task}. Context `{JobArrival Job}. Context `{JobCost Job}. (** To begin with, we establish an auxiliary rewriting lemma that allows us to introduce a [filter] on the considered set of jobs, provided the filter predicate [P2] is implied by the job-selection predicate [P1]. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job

forall (P1 P2 : pred Job) (jobs : seq Job), (forall j : Job, j \in jobs -> P1 j -> P2 j) -> workload_of_jobs P1 jobs = workload_of_jobs P1 [seq j <- jobs | P2 j]
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job

forall (P1 P2 : pred Job) (jobs : seq Job), (forall j : Job, j \in jobs -> P1 j -> P2 j) -> workload_of_jobs P1 jobs = workload_of_jobs P1 [seq j <- jobs | P2 j]
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
P1, P2: pred Job
jobs: seq Job
IMPL: forall j : Job, j \in jobs -> P1 j -> P2 j

workload_of_jobs P1 jobs = workload_of_jobs P1 [seq j <- jobs | P2 j]
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
P1, P2: pred Job
jobs: seq Job
IMPL: forall j : Job, j \in jobs -> P1 j -> P2 j

\sum_(i <- jobs | (i \in jobs) && P1 i) job_cost i = \sum_(i <- jobs | [&& i \in jobs, P2 i & P1 i]) job_cost i
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
P1, P2: pred Job
jobs: seq Job
IMPL: forall j : Job, j \in jobs -> P1 j -> P2 j
j: Job

(j \in jobs) && P1 j = [&& j \in jobs, P2 j & P1 j]
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
P1, P2: pred Job
jobs: seq Job
IMPL: forall j : Job, j \in jobs -> P1 j -> P2 j
j: Job
IN: j \in jobs

true && P1 j = [&& true, P2 j & P1 j]
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
P1, P2: pred Job
jobs: seq Job
IMPL: forall j : Job, j \in jobs -> P1 j -> P2 j
j: Job
IN: j \in jobs

P1 j = P2 j && P1 j
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
P1, P2: pred Job
jobs: seq Job
IMPL: forall j : Job, j \in jobs -> P1 j -> P2 j
j: Job
IN: j \in jobs
P1j: ~~ P1 j

false = P2 j && false
by rewrite andbF. Qed. (** Next, consider any job arrival sequence consistent with the arrival times of the jobs. *) Variable arr_seq : arrival_sequence Job. Hypothesis H_consistent : consistent_arrival_times arr_seq. (** If at some point in time [t] the predicate [P] by which we select jobs from the set of arrivals in an interval <<[t1, t2)>> becomes certainly false, then we may disregard all jobs arriving at time [t] or later. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq

forall (P : Job -> bool) (t1 : instant) (t2 t : nat), t <= t2 -> (forall j : Job, j \in arrivals_between arr_seq t1 t2 -> t <= job_arrival j -> ~~ P j) -> workload_of_jobs P (arrivals_between arr_seq t1 t2) = workload_of_jobs P (arrivals_between arr_seq t1 t)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq

forall (P : Job -> bool) (t1 : instant) (t2 t : nat), t <= t2 -> (forall j : Job, j \in arrivals_between arr_seq t1 t2 -> t <= job_arrival j -> ~~ P j) -> workload_of_jobs P (arrivals_between arr_seq t1 t2) = workload_of_jobs P (arrivals_between arr_seq t1 t)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
P: Job -> bool
t1: instant
t2, t: nat
LE: t <= t2
IMPL: forall j : Job, j \in arrivals_between arr_seq t1 t2 -> t <= job_arrival j -> ~~ P j

workload_of_jobs P (arrivals_between arr_seq t1 t2) = workload_of_jobs P (arrivals_between arr_seq t1 t)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
P: Job -> bool
t1: instant
t2, t: nat
LE: t <= t2
IMPL: forall j : Job, j \in arrivals_between arr_seq t1 t2 -> t <= job_arrival j -> ~~ P j

workload_of_jobs P (arrivals_between arr_seq t1 t2) = workload_of_jobs P [seq j <- arrivals_between arr_seq t1 t2 | job_arrival j < t]
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
P: Job -> bool
t1: instant
t2, t: nat
LE: t <= t2
IMPL: forall j : Job, j \in arrivals_between arr_seq t1 t2 -> t <= job_arrival j -> ~~ P j
j: Job
IN: j \in arrivals_between arr_seq t1 t2
Pj: P j

job_arrival j < t
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
P: Job -> bool
t1: instant
t2, t: nat
LE: t <= t2
IMPL: forall j : Job, j \in arrivals_between arr_seq t1 t2 -> t <= job_arrival j -> ~~ P j
j: Job
IN: j \in arrivals_between arr_seq t1 t2
Pj: P j
TAIL: t <= job_arrival j

false
by move: (IMPL j IN TAIL) => /negP. Qed. (** For simplicity, let's define a local name. *) Let arrivals_between := arrivals_between arr_seq. (** We observe that the cumulative workload of all jobs arriving in a time interval <<[t1, t2)>> and respecting a predicate [P] can be split into two parts. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job

forall (t t1 t2 : nat) (P : pred Job), t1 <= t <= t2 -> workload_of_jobs P (arrivals_between t1 t2) = workload_of_jobs P (arrivals_between t1 t) + workload_of_jobs P (arrivals_between t t2)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job

forall (t t1 t2 : nat) (P : pred Job), t1 <= t <= t2 -> workload_of_jobs P (arrivals_between t1 t2) = workload_of_jobs P (arrivals_between t1 t) + workload_of_jobs P (arrivals_between t t2)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
t, t1, t2: nat
P: pred Job
GE: t1 <= t
LE: t <= t2

workload_of_jobs P (arrivals_between t1 t2) = workload_of_jobs P (arrivals_between t1 t) + workload_of_jobs P (arrivals_between t t2)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
t, t1, t2: nat
P: pred Job
GE: t1 <= t
LE: t <= t2

\sum_(j <- arrival_sequence.arrivals_between arr_seq t1 t2 | P j) job_cost j = \sum_(j <- arrival_sequence.arrivals_between arr_seq t1 t | P j) job_cost j + \sum_(j <- arrival_sequence.arrivals_between arr_seq t t2 | P j) job_cost j
by rewrite (arrivals_between_cat _ _ t) // big_cat. Qed. (** Consider a job [j] ... *) Variable j : Job. (** ... and a duplicate-free sequence of jobs [jobs]. *) Variable jobs : seq Job. Hypothesis H_jobs_uniq : uniq jobs. (** Further, assume that [j] is contained in [jobs]. *) Hypothesis H_j_in_jobs : j \in jobs. (** To help with rewriting, we prove that the workload of [jobs] minus the job cost of [j] is equal to the workload of all jobs except [j]. To define the workload of all jobs, since [workload_of_jobs] expects a predicate, we use [predT], which is the always-true predicate. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs

workload_of_jobs (fun jhp : Job => jhp != j) jobs = workload_of_jobs predT jobs - job_cost j
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs

workload_of_jobs (fun jhp : Job => jhp != j) jobs = workload_of_jobs predT jobs - job_cost j
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs

\sum_(y <- rem (T:=Job) j jobs | y != j) job_cost y = \sum_(j <- jobs) job_cost j - job_cost j
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs

\sum_(y <- rem (T:=Job) j jobs | y != j) job_cost y = \sum_(y <- rem (T:=Job) j jobs) job_cost y
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs

\sum_(i <- rem (T:=Job) j jobs | (i \in rem (T:=Job) j jobs) && (i != j)) job_cost i = \sum_(i <- rem (T:=Job) j jobs | (i \in rem (T:=Job) j jobs) && true) job_cost i
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
j': Job

(j' \in rem (T:=Job) j jobs) && (j' != j) = (j' \in rem (T:=Job) j jobs) && true
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
j': Job

(j' \in rem (T:=Job) j jobs) && (j' != j) = (j' \in rem (T:=Job) j jobs)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
j': Job
INjobs: (j' \in rem (T:=Job) j jobs) = true

true && (j' != j) = true
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
j': Job
INjobs: (j' \in rem (T:=Job) j jobs) = true
EQUAL: j' = j

False
by rewrite EQUAL mem_rem_uniqF in INjobs. Qed. (** In this section, we prove the relation between two different ways of constraining [workload_of_jobs] to only those jobs that arrive prior to a given time. *) Section Subset. (** Assume that arrival times are consistent and that arrivals are unique. *) Hypothesis H_valid_arrival_sequence : valid_arrival_sequence arr_seq. (** Consider a time interval <<[t1, t2)>> and a time instant [t]. *) Variable t1 t2 t : instant. Hypothesis H_t1_le_t2 : t1 <= t2. (** Let [P] be an arbitrary predicate on jobs. *) Variable P : pred Job. (** Consider the window <<[t1,t2)>>. We prove that the total workload of the jobs arriving in this window before some [t] is the same as the workload of the jobs arriving in <<[t1,t)>>. Note that we only require [t1] to be less-or-equal than [t2]. Consequently, the interval <<[t1,t)>> may be empty. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
H_t1_le_t2: t1 <= t2
P: pred Job

workload_of_jobs (fun j : Job => (job_arrival j <= t) && P j) (arrivals_between t1 t2) <= workload_of_jobs [eta P] (arrivals_between t1 (t + ε))
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
H_t1_le_t2: t1 <= t2
P: pred Job

workload_of_jobs (fun j : Job => (job_arrival j <= t) && P j) (arrivals_between t1 t2) <= workload_of_jobs [eta P] (arrivals_between t1 (t + ε))
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job

workload_of_jobs (fun j : Job => (job_arrival j <= t) && P j) (arrivals_between t1 t2) <= workload_of_jobs [eta P] (arrivals_between t1 (t + ε))
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job

\sum_(i <- arrivals_between t1 t2 | [&& i \in arrivals_between t1 t2, job_arrival i <= t & P i]) job_cost i <= \sum_(j <- arrivals_between t1 (t + ε) | P j) job_cost j
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job

\sum_(i <- [seq i <- arrivals_between t1 t2 | i \in arrivals_between t1 t2 & (job_arrival i <= t) && P i]) job_cost i <= \sum_(i <- [seq x <- arrivals_between t1 (t + ε) | P x]) job_cost i
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job

{subset [seq i <- arrivals_between t1 t2 | i \in arrivals_between t1 t2 & (job_arrival i <= t) && P i] <= [seq x <- arrivals_between t1 (t + ε) | P x]}
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'

j' \in [seq x <- arrivals_between t1 (t + ε) | P x]
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'

j' \in arrivals_between t1 (t + ε)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'

arrives_in arr_seq j'
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'
t1 <= job_arrival j' < t + ε
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'

arrives_in arr_seq j'
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'
t1 <= job_arrival j' < t + ε
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'

t1 <= job_arrival j' < t + ε
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
A: j' \in arrivals_between t1 t2
C: job_arrival j' <= t
D: P j'

t1 <= job_arrival j' < t + ε
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_valid_arrival_sequence: valid_arrival_sequence arr_seq
t1, t2, t: instant
P: pred Job
j': Job
C: job_arrival j' <= t
D: P j'
A: t1 <= job_arrival j'
E: job_arrival j' < t2

t1 <= job_arrival j' < t + ε
by unfold ε; apply/andP; split; lia. Qed. End Subset. (** In this section, we prove a few useful properties regarding the predicate of [workload_of_jobs]. *) Section PredicateProperties. (** First, we show that workload of jobs for an unsatisfiable predicate is equal to 0. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs

workload_of_jobs pred0 jobs = 0
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs

workload_of_jobs pred0 jobs = 0
by rewrite /workload_of_jobs; apply big_pred0. Qed. (** Next, consider two arbitrary predicates [P] and [P']. *) Variable P P' : pred Job. (** We show that [workload_of_jobs] conditioned on [P] can be split into two summands: (1) [workload_of_jobs] conditioned on [P /\ P'] and (2) [workload_of_jobs] conditioned on [P /\ ~~ P']. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job

workload_of_jobs P jobs = workload_of_jobs (fun j : Job => P j && P' j) jobs + workload_of_jobs (fun j : Job => P j && ~~ P' j) jobs
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job

workload_of_jobs P jobs = workload_of_jobs (fun j : Job => P j && P' j) jobs + workload_of_jobs (fun j : Job => P j && ~~ P' j) jobs
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job

\sum_(i <- jobs) (if P i then job_cost i else 0) = \sum_(i <- jobs) ((if P i && P' i then job_cost i else 0) + (if P i && ~~ P' i then job_cost i else 0))
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job
j': Job
IN: j' \in jobs

(if P j' then job_cost j' else 0) = (if P j' && P' j' then job_cost j' else 0) + (if P j' && ~~ P' j' then job_cost j' else 0)
by destruct (P _), (P' _); simpl; lia. Qed. (** We show that if [P] is indistinguishable from [P'] on set [jobs], then [workload_of_jobs] conditioned on [P] is equal to [workload_of_jobs] conditioned on [P']. *)
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job

{in jobs, P =1 P'} -> workload_of_jobs P jobs = workload_of_jobs P' jobs
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job

{in jobs, P =1 P'} -> workload_of_jobs P jobs = workload_of_jobs P' jobs
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job
EQUIV: {in jobs, P =1 P'}

workload_of_jobs P jobs = workload_of_jobs P' jobs
Task: TaskType
H: TaskCost Task
Job: JobType
H0: JobTask Job Task
H1: JobArrival Job
H2: JobCost Job
arr_seq: arrival_sequence Job
H_consistent: consistent_arrival_times arr_seq
arrivals_between:= arrival_sequence.arrivals_between arr_seq: instant -> instant -> seq Job
j: Job
jobs: seq Job
H_jobs_uniq: uniq jobs
H_j_in_jobs: j \in jobs
P, P': pred Job
EQUIV: {in jobs, P =1 P'}

\sum_(i <- jobs) (if P i then job_cost i else 0) = \sum_(i <- jobs) (if P' i then job_cost i else 0)
by apply: eq_big_seq => j' IN; rewrite EQUIV. Qed. End PredicateProperties. End WorkloadFacts.