Library prosa.classic.model.schedule.global.basic.schedule

Require Import prosa.classic.util.all
               prosa.classic.model.arrival.basic.job prosa.classic.model.arrival.basic.task prosa.classic.model.arrival.basic.arrival_sequence.
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop.

Module Schedule.

  Export ArrivalSequence.

  Definition processor (num_cpus: nat) := 'I_num_cpus.

  Section ScheduleDef.

    Variable Job: eqType.

    Variable num_cpus: nat.

    Definition schedule :=
      processor num_cpus → time → option Job.

  End ScheduleDef.

  Section ScheduledJobs.

    Context {Job: eqType}.
    Variable job_arrival: Job → time.

    Context {arr_seq: arrival_sequence Job}.

    Variable job_cost: Job → time.
    Context {num_cpus: nat}.

    Variable sched: schedule Job num_cpus.
    Variable j: Job.

    Definition scheduled_on (cpu: processor num_cpus) (t: time) :=
      sched cpu t == Some j.

    Definition scheduled (t: time) :=
      [∃ cpu, scheduled_on cpu t].

    Definition is_idle (cpu: processor num_cpus) (t: time) :=
      sched cpu t = None.

    Definition service_at (t: time) :=
      \sum_(cpu < num_cpus | scheduled_on cpu t) 1.

    Definition service (t': time) := \sum_(0 ≤ t < t') service_at t.

    Definition service_during (t1 t2: time) := \sum_(t1 ≤ t < t2) service_at t.

    Definition completed (t: time) := service t ≥ job_cost j.

    Definition pending (t: time) := has_arrived job_arrival j t && ~~completed t.

    Definition backlogged (t: time) := pending t && ~~scheduled t.

    Definition carried_in (t1: time) := arrived_before job_arrival j t1 && ~~ completed t1.

    Definition carried_out (t1 t2: time) := arrived_before job_arrival j t2 && ~~ completed t2.

    Definition jobs_scheduled_at (t: time) :=
      \cat_(cpu < num_cpus) make_sequence (sched cpu t).

    Definition jobs_scheduled_between (t1 t2: time) :=
      undup (\cat_(t1 ≤ t < t2) jobs_scheduled_at t).

  End ScheduledJobs.

  Section ValidSchedules.

    Context {Job: eqType}.
    Variable job_arrival: Job → time.
    Variable job_cost: Job → time.

    Context {num_cpus: nat}.
    Variable sched: schedule Job num_cpus.

    Definition sequential_jobs :=
      ∀ j t cpu1 cpu2,
        sched cpu1 t = Some j → sched cpu2 t = Some j → cpu1 = cpu2.

    Definition jobs_must_arrive_to_execute :=
      ∀ j t,
        scheduled sched j t →
        has_arrived job_arrival j t.

    Definition completed_jobs_dont_execute :=
      ∀ j t, service sched j t ≤ job_cost j.

    Definition jobs_come_from_arrival_sequence (arr_seq: arrival_sequence Job) :=
      ∀ j t, scheduled sched j t → arrives_in arr_seq j.

  End ValidSchedules.

  Section JobLemmas.

    Context {Job: eqType}.
    Variable job_arrival: Job → time.
    Variable job_cost: Job → time.

    Context {num_cpus: nat}.
    Variable sched: schedule Job num_cpus.

    Variable j: Job.

    Section Basic.

      Lemma not_scheduled_no_service :
        ∀ t,
          ~~ scheduled sched j t = (service_at sched j t == 0).

      Lemma cumulative_service_implies_service :
        ∀ t1 t2,
          service_during sched j t1 t2 != 0 →
          ∃ t,
            t1 ≤ t < t2 ∧
            service_at sched j t != 0.

      Lemma service_implies_cumulative_service:
        ∀ t t1 t2,
          t1 ≤ t < t2 →
          service_at sched j t != 0 →
          service_during sched j t1 t2 != 0.

    End Basic.

    Section SequentialJobs.

      Hypothesis H_sequential_jobs: sequential_jobs sched.

      Lemma service_at_most_one :
        ∀ t, service_at sched j t ≤ 1.

      Lemma cumulative_service_le_delta :
        ∀ t delta, service_during sched j t (t + delta) ≤ delta.

    End SequentialJobs.

    Section Completion.

      Hypothesis H_completed_jobs:
        completed_jobs_dont_execute job_cost sched.

      Lemma completion_monotonic :
        ∀ t t',
          t ≤ t' →
          completed job_cost sched j t →
          completed job_cost sched j t'.

      Lemma completed_implies_not_scheduled :
        ∀ t,
          completed job_cost sched j t →
          ~~ scheduled sched j t.

      Lemma cumulative_service_le_job_cost :
        ∀ t t',
          service_during sched j t t' ≤ job_cost j.

    End Completion.

    Section Arrival.

      Hypothesis H_jobs_must_arrive:
        jobs_must_arrive_to_execute job_arrival sched.

      Lemma service_before_job_arrival_zero :
        ∀ t,
          t < job_arrival j →
          service_at sched j t = 0.

      Lemma cumulative_service_before_job_arrival_zero :
        ∀ t1 t2,
          t2 ≤ job_arrival j →
          \sum_(t1 ≤ i < t2) service_at sched j i = 0.

      Lemma service_before_arrival_eq_service_during :
        ∀ t0 t,
          t0 ≤ job_arrival j →
          \sum_(t0 ≤ t < job_arrival j + t) service_at sched j t =
          \sum_(job_arrival j ≤ t < job_arrival j + t) service_at sched j t.

    End Arrival.

    Section Pending.

      Hypothesis H_jobs_must_arrive:
        jobs_must_arrive_to_execute job_arrival sched.

      Hypothesis H_completed_jobs:
        completed_jobs_dont_execute job_cost sched.

      Lemma scheduled_implies_pending:
        ∀ t,
          scheduled sched j t →
          pending job_arrival job_cost sched j t.

    End Pending.

  End JobLemmas.

  Section ScheduledJobsLemmas.

    Context {Job: eqType}.

    Context {num_cpus: nat}.
    Variable sched: schedule Job num_cpus.

    Section Membership.

      Lemma mem_scheduled_jobs_eq_scheduled :
        ∀ j t,
          j \in jobs_scheduled_at sched t = scheduled sched j t.

    End Membership.

    Section Uniqueness.

      Hypothesis H_sequential_jobs : sequential_jobs sched.

      Lemma scheduled_jobs_uniq :
        ∀ t,
          uniq (jobs_scheduled_at sched t).

    End Uniqueness.

    Section NumberOfJobs.

      Lemma num_scheduled_jobs_le_num_cpus :
        ∀ t,
          size (jobs_scheduled_at sched t) ≤ num_cpus.

    End NumberOfJobs.

  End ScheduledJobsLemmas.

End Schedule.

Module ScheduleOfSporadicTask.

  Import SporadicTask Job.
  Export Schedule.

  Section ScheduledJobs.

    Context {sporadic_task: eqType}.
    Context {Job: eqType}.
    Variable job_task: Job → sporadic_task.

    Context {num_cpus: nat}.
    Variable sched: schedule Job num_cpus.

    Variable tsk: sporadic_task.

    Definition task_scheduled_on (cpu: processor num_cpus) (t: time) :=
      if (sched cpu t) is Some j then
        (job_task j == tsk)
      else false.

      Definition task_is_scheduled (t: time) :=
        [∃ cpu, task_scheduled_on cpu t].

    Definition jobs_of_task_scheduled_between (t1 t2: time) :=
      filter (fun j ⇒ job_task j == tsk)
             (jobs_scheduled_between sched t1 t2).

  End ScheduledJobs.

  Section ScheduleProperties.

    Context {sporadic_task: eqType}.
    Context {Job: eqType}.
    Variable job_cost: Job → time.
    Variable job_task: Job → sporadic_task.

    Context {num_cpus: nat}.
    Variable sched: schedule Job num_cpus.

    Definition jobs_of_same_task_dont_execute_in_parallel :=
      ∀ j j' t,
        job_task j = job_task j' →
        scheduled sched j t →
        scheduled sched j' t →
        j = j'.

  End ScheduleProperties.

  Section BasicLemmas.

    Context {sporadic_task: eqType}.
    Variable task_cost: sporadic_task → time.
    Variable task_deadline: sporadic_task → time.

    Context {Job: eqType}.
    Variable job_cost: Job → time.
    Variable job_deadline: Job → time.
    Variable job_task: Job → sporadic_task.

    Context {num_cpus: nat}.
    Variable sched: schedule Job num_cpus.

    Hypothesis jobs_dont_execute_after_completion :
       completed_jobs_dont_execute job_cost sched.

    Variable tsk: sporadic_task.

    Variable j: Job.
    Hypothesis H_job_of_task: job_task j = tsk.
    Hypothesis valid_job:
      valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.

    Lemma cumulative_service_le_task_cost :
        ∀ t t',
          service_during sched j t t' ≤ task_cost tsk.

  End BasicLemmas.

End ScheduleOfSporadicTask.