Parcoursup / Calcul de l'ordre d'appel des candidats index


module IQX
  use int.Int
  use seq.Seq
  use proofs.ordre_appel.seq_voeux.SeqVoeux
  use proofs.ordre_appel.seq_voeux.SeqVoeuxTaux
  use fr.parcoursup.whyml.ordreappel.algo.voeu_classe.VoeuClasse
  use fr.parcoursup.whyml.ordreappel.algo.enum_map.EnumMap
  use fr.parcoursup.whyml.ordreappel.algo.enum_map.AllDistincts

  (*
   * Invariant qui lie la taille du groupe de classement, de l'ordre d'appel
   * courant et des files de voeux
   *)
  predicate iqx_0 (nb_v nb_b nb_ds : int) (oa : seq_voeu) (m : EnumMap.t) =
    nb_v = Seq.length oa + EnumMap.get_nb_voeux_classes m &&
    nb_b = SeqVoeux.nb_boursiers oa + EnumMap.get_nb_boursiers m &&
    nb_ds = SeqVoeux.nb_du_secteur oa + EnumMap.get_nb_du_secteur m

  predicate iqx_2_loc (nb_b : int) (tx_b : Taux.t) (oa : seq_voeu) (i : int) =
    taux_b_contraignant tx_b oa[..i] nb_b -> est_boursier oa[i]

  predicate iqx_2 (nb_b : int) (tx_b : Taux.t) (oa : seq_voeu) =
    forall i. 0 <= i < length oa ->
      taux_b_contraignant tx_b oa[..i] nb_b -> est_boursier oa[i]

  let lemma iqx_2_equiv (nb_b : int) (tx_b : Taux.t) (oa : seq_voeu)
    ensures { iqx_2 nb_b tx_b oa <-> forall i. 0 <= i < length oa -> iqx_2_loc nb_b tx_b oa i }
  =
    for i = 0 to length oa-1 do
      invariant { forall j. 0 <= j < i -> (taux_b_contraignant tx_b oa[..j] nb_b  -> est_boursier oa[j])
		              <-> iqx_2_loc nb_b tx_b oa j }
    done

  predicate iqx_3ds_loc (nb_ds : int) (oa : seq_voeu) (k : int) =
    not remains_du_secteur oa[..k] nb_ds -> hors_secteur_seulement oa[k..]

  predicate iqx_3ds (nb_ds : int) (oa : seq_voeu) =
    forall k. 0 <= k <= length oa -> iqx_3ds_loc nb_ds oa k

  predicate iqx_3b_loc (nb_b : int) (oa : seq_voeu) (k : int) =
    not remains_boursiers oa[..k] nb_b -> non_boursiers_seulement oa[k..]

  predicate iqx_3b (nb_b : int) (oa : seq_voeu) =
    forall k. 0 <= k <= length oa -> iqx_3b_loc nb_b oa k

  predicate iqx_3 (nb_b nb_ds : int) (oa : seq_voeu) =
    iqx_3b nb_b oa && iqx_3ds nb_ds oa

  predicate iqx_4 (oa : seq_voeu) (m : EnumMap.t) =
    enummap_seq_all_distincts oa m

  predicate iqx_5 (oa : seq_voeu) (m : EnumMap.t) =
    (forall i. 0 <= i < Seq.length oa -> get_rang oa[i] >= 1) &&
    (forall v. enummap_contains m v -> get_rang v >= 1)

end

module IQX_Snoc
  use int.Int
  use set.Fset
  use seq.Seq
  use proofs.lib.seq.Seq
  use proofs.ordre_appel.seq_voeux.SeqVoeux
  use proofs.ordre_appel.seq_voeux.SeqVoeuxTaux
  use proofs.ordre_appel.seq_voeux.SeqVoeuxGroupe
  use proofs.ordre_appel.seq_voeux.SeqVoeuxDistincts
  use proofs.ordre_appel.eligibles.Eligibles
  use proofs.ordre_appel.eligibles.ValidEligibles
  use proofs.ordre_appel.invariants.iq0.IQ0
  use fr.parcoursup.whyml.ordreappel.algo.voeu_classe.VoeuClasse
  use fr.parcoursup.whyml.ordreappel.algo.voeu_classe.VoeuClasse_Props
  use fr.parcoursup.whyml.ordreappel.algo.voeu_classe.PQueueVoeuxClasses as PQueue
  use fr.parcoursup.whyml.ordreappel.algo.enum_map.EnumMap
  use fr.parcoursup.whyml.ordreappel.algo.enum_map.AllDistincts
  use export IQX

  let lemma om_m_move (oa : seq_voeu) (om m : EnumMap.t) (x : voeu) (nbb nbr : int)
    requires { nbb = SeqVoeux.nb_boursiers oa + EnumMap.get_nb_boursiers om }
    requires { nbr = SeqVoeux.nb_du_secteur oa + EnumMap.get_nb_du_secteur om }
    requires { [@expl:alld m] enummap_all_distincts om }
    requires { [@expl:x selected] enummap_pop_v om m x }
    ensures { nbb = SeqVoeux.nb_boursiers (snoc oa x) + EnumMap.get_nb_boursiers m }
    ensures { nbr = SeqVoeux.nb_du_secteur (snoc oa x) + EnumMap.get_nb_du_secteur m }
  =
    if est_boursier x then begin
      assert { SeqVoeux.nb_boursiers (snoc oa x) + EnumMap.get_nb_boursiers m =
               (SeqVoeux.nb_boursiers oa + 1) + (EnumMap.get_nb_boursiers om) - 1 = nbb };
    end;
    if est_du_secteur x then begin
      assert { SeqVoeux.nb_du_secteur (snoc oa x) + EnumMap.get_nb_du_secteur m =
               (SeqVoeux.nb_du_secteur oa + 1) + (EnumMap.get_nb_du_secteur om) - 1 = nbr };
    end

  let lemma iqx_0_snoc (nb_v nb_b nb_ds : int) (oa : seq_voeu) (om m : EnumMap.t) (x : voeu)
    requires { [@expl:iqx0 oa] iqx_0 nb_v nb_b nb_ds oa om }
    requires { [@expl:alld m] enummap_all_distincts om }
    requires { [@expl:x selected] enummap_pop_v om m x }

    ensures { iqx_0 nb_v nb_b nb_ds (snoc oa x) m }
    ensures { est_boursier x -> nb_b > 0 }
    ensures { est_du_secteur x -> nb_ds > 0 }
    ensures { est_boursier x -> remains_boursiers oa nb_b }
    ensures { est_du_secteur x -> remains_du_secteur oa nb_ds }
  =
    om_m_move oa om m x nb_b nb_ds

  let lemma iqx_0_empty (op oak : seq_voeu) (m : EnumMap.t )
    requires { iq0 op oak m }
    requires { length op = get_nb_voeux_classes m}
    requires { nb_boursiers op = EnumMap.get_nb_boursiers m}
    requires { nb_du_secteur op = EnumMap.get_nb_du_secteur m}
    requires { oak = Seq.empty }
    ensures { iqx_0 (length op) (nb_boursiers op) (nb_du_secteur op) oak m }
  =
    ()

  (* IQ1/L3 *)
  let lemma iqx_2_snoc (cB cR : bool) (nb_b : int) (tx_b : Taux.t) (oa : seq_voeu) (om : EnumMap.t)
                       (eligibles: PQueue.t) (x : voeu)
    requires { [@expl:valid eligibles] meilleur_eligible cB cR om eligibles x }
    requires { [@expl:cB equiv tx_b contraignant] cB = taux_b_contraignant tx_b oa nb_b }
    requires { [@expl:iqx_2(oa)] iqx_2 nb_b tx_b oa }
    ensures { iqx_2 nb_b tx_b (snoc oa x) }
  =
    let s' = snoc oa x in
    for i = 0 to length s'-1 do
      invariant { forall j. 0 <= j < i -> iqx_2_loc nb_b tx_b s' j }
      if i < length s'-1 then
        assert { iqx_2_loc nb_b tx_b oa i }
      else if taux_b_contraignant tx_b s'[..i] nb_b then
      begin
        assert { cB && s'[i] = x };
	      assert { not Fset.is_empty eligibles -> est_eligible_p cB cR x };
	      assert { Fset.is_empty eligibles -> est_boursier_hors_secteur s'[i] };
      end else
        assert { iqx_2_loc nb_b tx_b s' i }
    done

  let lemma iqx_2_prefix (nb_b : int) (tx_b : Taux.t) (s : seq_voeu)
    requires { iqx_2 nb_b tx_b s }
    ensures { forall i. 0 <= i < length s -> iqx_2 nb_b tx_b s[..i] }
  = ()

  let lemma iqx_3ds_snoc (nb_v nb_b nb_ds : int) (oa : seq_voeu) (om m : EnumMap.t) (x : voeu)
    requires { iqx_0 nb_v nb_b nb_ds oa om }
    requires { [@expl:x selected] enummap_pop_v om m x }
    requires { [@expl:iqx_3ds(oa)] iqx_3ds nb_ds oa }
    ensures { iqx_3ds nb_ds (snoc oa x) }
  =
    assert { [@expl:x ds -> remains ds] est_du_secteur x -> remains_du_secteur oa nb_ds };
    let s = snoc oa x in
    if est_du_secteur x then
    begin
      assert { forall k. 0 <= k < length s -> s[..k] == oa[..k] };
      assert { iqx_3ds_loc nb_ds s (length s) };
      assert { forall k. 0 <= k <= length s -> iqx_3ds_loc nb_ds s k };
      return;
    end;
    for k = 0 to length s do
      invariant { forall i. 0 <= i < k -> iqx_3ds_loc nb_ds s i }
      assert { est_hors_secteur x };
      if k < length s then
      begin
        if not remains_du_secteur oa[..k] nb_ds then begin
          assert { hors_secteur_seulement (snoc oa[k..] x) };
          hors_secteur_seulement_snoc oa[k..] x;
          assert { s[k..] == snoc oa[k..] x };
          assert { hors_secteur_seulement s[k..] };
	      end;
      end else
        assert { iqx_3ds_loc nb_ds s k };
    done

  let lemma iqx_3b_snoc (nb_v nb_b nb_ds : int) (oa : seq_voeu) (om m : EnumMap.t) (x : voeu)
    requires { iqx_0 nb_v nb_b nb_ds oa om }
    requires { [@expl:x selected] enummap_pop_v om m x }
    requires { [@expl:iqx_3b(oa)] iqx_3b nb_b oa }
    ensures { iqx_3b nb_b (snoc oa x) }
  =
    assert { [@expl:x b -> remains b] est_boursier x -> remains_boursiers oa nb_b };
    let s = snoc oa x in
    for k = 0 to length s do
      invariant { forall i. 0 <= i < k -> iqx_3b_loc nb_b s i }
      if k <= length s - 1 then begin
         if est_boursier x then begin
           assert { remains_boursiers oa[..k] nb_b };
           assert { remains_boursiers s[..k] nb_b };
           assert { iqx_3b_loc nb_b s k };
         end else if not remains_boursiers oa[..k] nb_b then begin
	         assert { non_boursiers_seulement (snoc oa[k..] x) };
           non_boursiers_seulement_snoc oa[k..] x;
	         assert { s[k..] == snoc oa[k..] x };
           assert { non_boursiers_seulement s[k..] };
           assert { iqx_3b_loc nb_b oa k };
           assert { iqx_3b_loc nb_b s k };
	       end;
      end else begin
        assert { iqx_3b_loc nb_b s k };
      end
    done

  let lemma iqx_3_snoc (nb_v nb_b nb_ds : int) (oa : seq_voeu) (om m : EnumMap.t) (x : voeu)
    requires { iqx_0 nb_v nb_b nb_ds oa om }
    requires { [@expl:x selected] enummap_pop_v om m x }
    requires { [@expl:iqx_3(oa)] iqx_3 nb_b nb_ds oa }
    ensures { iqx_3 nb_b nb_ds (snoc oa x)  }
  =
    iqx_3b_snoc nb_v nb_b nb_ds oa om m x;
    iqx_3ds_snoc nb_v nb_b nb_ds oa om m x

  let lemma iqx_3_empty (op oak : seq_voeu) (m : EnumMap.t)
    requires { iq0 op oak m }
    requires { oak = Seq.empty }
    ensures { iqx_3 (nb_boursiers op) (nb_du_secteur op) oak }
  =
    ()

  let lemma iqx_4_snoc (s : seq_voeu) (om m : EnumMap.t) (x : voeu)
    requires {[@expl:alld(om)] enummap_all_distincts om }
    requires {[@expl:alld(s)] all_distincts s }
    requires {[@expl:alld(om + s)] enummap_seq_distincts om s }
    requires {[@expl:x = om-m] enummap_contains om x && not enummap_contains m x }
    requires {[@expl:m included in om] forall v. enummap_contains m v -> enummap_contains om v }
    ensures { enummap_seq_distincts m (snoc s x) }
    ensures { enummap_all_distincts m }
    ensures { all_distincts (snoc s x) }
  = let s' = snoc s x in
    assert { forall i. 0 <= i < length s'-1 -> voeu_distinct s'[i] x };
    alld_snoc x s

  let lemma iqx_4_empty (op oak : seq_voeu) (m : EnumMap.t)
    requires { seq_groupe_ok op }
    requires { seq_rangs_sorted op }
    requires { iq0 op oak m }
    requires { oak = Seq.empty }
    ensures { iqx_4 oak m }
  =
    assert { enummap_all_distincts m }

  let lemma iqx_5_snoc (oa : seq_voeu) (om m : EnumMap.t) (x : voeu)
    (* requires {[@expl:alld(om)] enummap_all_distincts om }
    requires {[@expl:alld(s)] all_distincts s }
    requires {[@expl:alld(om + s)] enummap_seq_distincts om s }
    requires { [@expl:x = om-m] enummap_contains om x && not enummap_contains m x }
    requires { [@expl:m included in om] forall v. enummap_contains m v -> enummap_contains om v } *)
    requires { [@expl:pre iqx_5 / pop v] enummap_pop_v om m x }
    requires { [@expl:pre iqx_5 / iqx_5] iqx_5 oa om }
    ensures { iqx_5 (snoc oa x) m }
  = let s = snoc oa x in
    assert { s[length s - 1] = x };
    assert { enummap_contains om x };
    assert { get_rang x >= 1 };
    assert { forall i. 0 <= i < length s -> 1<= get_rang s[i] }

  let lemma iqx_5_empty (op s : seq_voeu) (m : EnumMap.t )
    requires { seq_groupe_ok op }
    requires { seq_rangs_sorted op }
    requires { iq0 op s m }
    requires { s = Seq.empty }
    ensures { iqx_5 s m }
  =
    assert { seq_rangs_ge_1 op };
    assert { forall v. enummap_contains m v -> seq_contains v op };
    assert { forall v. seq_contains v op -> get_rang v >= 1 };
    ()

end

(* generated on Thu Nov 21 02:04:27 UTC 2024 from rev:  *)

Generated by why3doc 1.7.2+git