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 jjob_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.