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


module Permutation

  use int.Int
  use map.Map

  predicate in_range (n: int) (f: int -> int) =
    forall i. 0 <= i < n -> 0 <= f i < n

  predicate injective (n: int) (f: int -> int) =
    forall i j. 0 <= i < n -> 0 <= j < n -> i <> j -> f i <> f j

  type permutation = {
    n: int;
    map: int -> int;
    inv: int -> int;
  } invariant { n >= 0 }
    invariant { in_range n map }
    invariant { in_range n inv }
    invariant { forall i. 0 <= i < n -> inv[map[i]] = i }
    invariant { forall i. 0 <= i < n -> map[inv[i]] = i }
  by { n = 0;
       map = (fun i -> i);
       inv = (fun i -> i); }

  meta coercion function map

  let function identity (n: int) : permutation
    requires { n >= 0 }
  =
  { n = n;
      map = (fun i -> i);
      inv = (fun i -> i); }

  let function compose_ranged_fun (n : int) (f1 f2 : int -> int) : int -> int
  requires { in_range n f1 }
  requires { in_range n f2 }
  ensures { in_range n result }
  = fun i -> f2 (f1 i)

  let function compose (p1 p2: permutation) : permutation
  requires { p1.n = p2.n }
  ensures { result.n = p1.n }
  ensures { result.map = compose_ranged_fun p1.n p1.map p2.map }
  = (

  let result =
    {
        n = p1.n ;
        map = compose_ranged_fun p1.n p1.map p2.map;
        inv = compose_ranged_fun p1.n p2.inv p1.inv;
      } in
      assert { result.n >= 0 };
      assert { in_range p1.n result.map };
      assert { in_range p1.n result.inv };
      result;
      )

  let function inverse (p: permutation) : (permutation) =
    { n = p.n; map = p.inv; inv = p.map; }

  let rec lemma from_map (n : int) (f : int -> int) : permutation
  requires { n >= 0 }
  requires { in_range n f }
  requires { injective n f }
  ensures { result.n = n  }
  ensures { result.map = f   }
  variant { n }
  =
  (
  if n = 0 then
    { n = 0; map = f; inv = f }
  else
    begin
    let x = f 0 in
    let rm = fun x k -> if k < x then k else k - 1 in
    let fx = fun k -> rm x (f (k+1)) in
    let invx = (from_map (n - 1) fx).inv in
    let insert0 = fun k -> if k < x then k else if k = x then 0 else k -1 in
      { n = n;
        map = f ;
        inv = fun k ->
          if k = x then 0
          else 1 + invx (rm x k)
        }
    end
  )

  let rec function first_not_id_rec (p : permutation) (i : int) : int
    requires { 0 <= i <= p.n }
    requires { forall k. 0<= k < i -> (p k) = k }
    ensures { 0 <= result <= p.n }
    ensures { forall k. 0<= k < result -> (p k) = k }
    ensures { result < p.n -> (p result) <> result }
    variant { p.n - i }
  =
    if i = p.n then
      p.n
    else if ((p.map i) <> i) then
      i
    else
      first_not_id_rec p (i+1)

  let function first_not_id (p : permutation) : int
    ensures { 0 <= result <= p.n }
    ensures { forall k. 0<= k < result -> p k = k }
    ensures { result < p.n -> p result <> result }
    ensures { result < p.n -> forall k. 0 <= k < p.n -> p k < result ->
              p (p k) = (p k)  < result }
    ensures { result < p.n -> forall k. 0 <= k < p.n -> p k < result ->
              k < result }
    ensures { result < p.n -> forall k. result <= k < p.n -> result <= p k }
  =
    first_not_id_rec p 0

   use seq.Seq

   let function permut (s : seq 'a) (p : permutation) : seq 'a
     requires { length s = p.n }
     ensures { length result = length s }
     ensures { forall k. 0 <= k < length s -> result[k] = s[p k] }
     ensures { forall k. 0 <= k < length s -> s[k] = result[p.inv k] }
   =
     create (length s) (fun k -> s[p.map k])
end

module Swap
  use int.Int
  use seq.Seq
  use Permutation

  let function fswap (i j k : int) : int =
    (if k = i then j else if k = j then i else k)

  let function transposition (n i j : int) : permutation
    requires { 0 <= i < n }
    requires { 0 <= j < n }
    ensures { result.n = n}
    ensures { result.map = fswap i j }
    ensures { result.inv = fswap i j }
  = { n = n; map = (fswap i j); inv = (fswap i j) }

  function swap (s:seq 'a) (i : int) (j : int) : seq 'a =
    permut s (transposition (length s) i j )

  let lemma swap_spec (s:seq 'a) (i : int) (j : int)
    requires{ 0 <= i < length s }
    requires{ 0 <= j < length s }
    ensures { length (swap s i j) = length s }
    ensures { (swap s i j)[i] = s[j] }
    ensures { (swap s i j)[j] = s[i] }
    ensures { forall k.
    	       0 <= k < length s ->
               k <> i ->
	       k <> j ->
    	      (swap s i j)[k] = s[k] }
   = ()
end

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

Generated by why3doc 1.7.2+git