Library probsa.rt.analysis.independent.task_workload

From probsa.rt.model Require Export events workload.

Section PrTaskWorkloadIndependence.

  Context {Ω} {μ : measure Ω}.

  Context {Task : TaskType}
          {D : TaskDeadline Task}.

  Context {Job : finType}
          {job_cost : JobCostRV Job Ω μ}
          {job_arrival : JobArrivalRV Job Ω μ}
          {job_task : JobTask Job Task}.

  Variable ts : seq Task.
  Hypothesis H_ts_uniq : uniq ts.
  Hypothesis H_jobs_from_ts : (j : Job), job_task j \in ts.

  Variable tsk : Task.
  Hypothesis H_tsk_in_ts : tsk \in ts.

  Hypothesis H_arrival_sequence_uniq : pr_arrival_sequence_uniq.
  Hypothesis H_arrivals_consistent : arr_seq_job_arrival_consistent.

  Let ξpart := partition_on_ξ μ : Ω_partition.
  Hypothesis job_costs_cond_independent :
     (ξ : I ξpart) `{!PosProb μ (ξpart◁{ξ})},
      independent
        [seq mkRvar (restrict μ (ξpart◁{ξ})) (job_cost j) | j <- index_enum Job].

  Variable ξ : I ξpart.
  Context {ρ : PosProb μ (ξpart◁{ξ})}.

For a task tsk ts, let [t1 tsk, t2 tsk) denote a time interval for each task in ts ...
  Variable (t1 t2 : Task instant).

... and let pr_task_workload tsk denote the task's conditional workload (w.r.t. the arrival sequence ξ) in the interval.
  Let pr_task_workload (tsk : Task) :=
    mkRvar _ (pr_workload_of_task tsk (t1 tsk) (t2 tsk))
    : rvar (restrict μ (ξpart◁{ξ})) [eqType of work].

Then probabilistic workloads pr_task_workload of distinct tasks in the corresponding intervals are independent.
  Lemma pr_task_workload_independence :
    independent [seq pr_task_workload tsk | tsk <- ts].
  Proof.
    haveINωξ] : ω, ξpart◁{ξ} ω.
    { move: (ρ) ⇒ POS.
      apply pr_pos_inv in POS.
      move: POS ⇒ [ω [IN _]].
      by ω; apply IN.
    }
    set (F xs :=
           (\sum_(j <-
                    map (fun '(j, _, _, _)j)
                        (filter (fun '(j, _, t1, t2)
                                   (is_some (job_arrival j ω) )
                                   && (t1 odflt0 (job_arrival j) ω < t2)) xs
                        )
                 | true)
             (sumn (map (fun '(_, c, _, _)c) (filter (fun '(jo, _, _, _)pred1 j jo ) xs)))
           )%nat
        ).
    set (f tsk ω j := (j, odflt0 (job_cost j) ω, t1 tsk, t2 tsk ) ).
    set (R :=
           fun tsk
             mkRvar (restrict μ (ξpart◁{ξ}))
                    (fun ω
                       map (f tsk ω) (filter (job_of_task tsk) (index_enum Job))
                    )
        ).
    apply: indep_irr; last first.
    { apply: (@indep_comp _ (restrict μ (ξpart◁{ξ})) _ _ R _ F ts).
      apply (@independent_flatten _ (restrict μ (ξpart◁{ξ})) _ _ _ f ts).
      rewrite allpairs_rvar; eapply indep_perm_eq.
      { apply perm_eq_allpairs_flatten with (F0 := job_task) ⇒ //.
        { by apply index_enum_uniq. }
        { by intros j IN; rewrite /job_of_task. }
        { by movetsk1 tsk2 j _ /eqP <- /eqP <-. }
      }
      rewrite -map_comp.
      apply: indep_pair_const_r; apply: indep_pair_const_r.
      apply indep_pair_swap, indep_pair_const_r.
      apply: (@indep_comp _ (restrict μ (ξpart◁{ξ})) _ _ (fun jmkRvar _ (job_cost j))).
      apply job_costs_cond_independent.
    }
    { clear tsk H_tsk_in_tstsk ωo IN POSo; unfold F.
      rewrite [RHS](@eq_bigl _ _ _ _ _ _ (fun jjob_of_task tsk j && job_of_task tsk j) );
        last by intros j; destruct job_of_task.
      rewrite big_mkcondr //= -[RHS]big_filter.
      erewrite perm_big.
      { apply congr_big; [reflexivity | done | movejo _].
        rewrite filter_map -map_comp -filter_predI sumnE big_map_id big_filter.
        by rewrite big_mkcondr big_pred1_eq //=.
      }
      { apply/allPj IN2.
        rewrite filter_map -map_comp -filter_predI //= !count_uniq_mem; first last.
        { by rewrite map_inj_uniq //; apply filter_uniq, index_enum_uniq. }
        { apply filter_uniq, bigcat_nat_uniq.
          { by intros s; apply H_arrival_sequence_uniq. }
          { intros jo t1' t2' INa INb.
            apply H_arrivals_consistent in INa.
            apply H_arrivals_consistent in INb.
            by rewrite INa in INb; inversion INb.
          }
        }
        { clear IN2; apply/eqP.
          destruct (j \in _ ) eqn:EQ.
          { symmetry; rewrite mem_filter.
            unfold "\o" in EQ; simpl in EQ.
            move: EQ ⇒ /mapP [jo INo EQ]; subst jo.
            move: INo; rewrite mem_filter //= ⇒ /andP [/andP [/andP [SOME NEQ] TSK] _].
            apply/eqP; rewrite eqb1; apply/andP; split ⇒ //.
            apply mem_bigcat with (x := odflt0 (job_arrival j) ω); first by rewrite mem_index_iota.
            destruct (job_arrival j ω) eqn:EQ; last by rewrite EQ in SOME.
            rewrite //= EQ; apply H_arrivals_consistent.
            clear IN; inversion INωξ as [IN].
            eapply pmf_restricted_pred in POSo; move: POSo ⇒ /eqP POSo; rewrite -POSo in IN.
            rewrite -EQ; apply eq_arr_seq_impl_eq_job_arrivalto.
            by move: IN ⇒ /eqP →.
          }
          { symmetry; apply/eqP; rewrite eqb0; apply/negPINO.
            move: EQ ⇒ /neqP EQ; apply: EQ; rewrite eqbF_neg negb_involutive.
            move: INO; rewrite mem_filter ⇒ /andP [TSK INO].
            apply mem_bigcat_nat_exists in INO; move: INO ⇒ [to [INO NEQ]].
            apply H_arrivals_consistent in INO; apply/mapP.
             j ⇒ //.
            have SO : job_arrival j ω = Some to.
            { clear IN; inversion INωξ as [IN]; move: IN ⇒ /eqP INω.
              apply pmf_restricted_pred in POSo; move: POSo ⇒ /eqP POSo; rewrite -INω in POSo.
              by erewrite eq_arr_seq_impl_eq_job_arrival; [erewrite INO | intros; rewrite POSo].
            }
            rewrite mem_filter; apply/andP; split; last by apply mem_index_enum.
            by apply/andP; split ⇒ //; apply/andP; split; rewrite SO.
          }
        }
      }
    }
  Qed.

End PrTaskWorkloadIndependence.