la méthode SumMax

Compléter pour obtenir une solution validée par Dafny.
method SumMax(x: int, y: int) returns (s: int, m: int)
    ensures s==x+y
    ensures x <= m && y <= m
    ensures m==x || m==y
{
    ...
}

à propos du maximum de deux entiers relatifs

On considère les deux relations suivantes, dont les arguments sont des entiers relatifs. Montrer qu'elles sont équivalentes.

les méthodes SumMaxBackwards

Compléter et proposer deux solutions distinctes validées par Dafny.
method SumMaxBackwards(s:int, m :int) returns (x:int, y:int)
    requires ...
    ensures s==x+y
    ensures x <= m && y <= m
    ensures m==x || m==y
{
    ...
}

la méthode CountToAndReturnN

Compléter pour obtenir une solution validée par Dafny.
method CountToAndReturnN(n: int) returns (r: int)
    requires ...
    ensures r == n 
{
    var i := 0;
    while i < n
      ...
    {
        i := i + 1;
    }
    r := i;
}

les méthodes Min2 et Min3

Compléter pour obtenir une solution validée par Dafny. Proposer plusieurs solutions pour Min3.
method Min2(x: int, y: int) returns (m:int)
    requires ...
    ensures ... // m est le min de x et y
{
    ...
}

method Min3(x: int, y: int, z: int) returns (m:int)
    requires ...
    ensures ... // m est le min de x, y et z
{
    ...
}

la fonction Fib et la méthode ComputeFib

Compléter pour obtenir une solution validée par Dafny.
function Fib(n: nat): nat
{
    if n < 2 then n else Fib(n-1) + Fib(n-2)
}

method ComputeFib(n: nat) returns (x:nat)
    ensure x == Fib(n)
{
    ...
}

la fonction Sum et la méthode ComputeSum

Considérer le code ci-dessous.
Montrer par récurrence sur n que Sum(n) est la somme des entiers de 0 à n inclus.
Compléter pour obtenir une solution validée par Dafny.
function Sum(n: nat): nat
{
    if n == 0  then 0 else n + Sum(n-1)
}

method ComputeSum(n: nat) returns (s:nat)
    ensures s == Sum(n)
{
    ...
}

la fonction Fact et la méthode ComputeFact

Compléter pour obtenir une solution validée par Dafny.
function factorial (n: nat): nat 
{
    if n == 0 then 1 else n*factorial(n - 1)
}

method computeFactorial(n: nat) returns (f: nat)
    ensures f == factorial(n)
{
    ... 
}

une méthode Carre pour élever un entier au carré

Considérer le code ci-dessous. Montrer que Compléter pour obtenir une solution validée par Dafny.
Généraliser pour un argument entier relatif.
method Carre(a: nat) returns (c: nat)
ensures c == a*a
{
  var i := 0;
  c := 0;
  while i != a
    ...
  {
    c := c + 2*i +1;
    i := i + 1;
  }
}

Une méthode Mult pour multiplier deux entiers

Considérer le code ci-dessous. Montrer que Compléter pour obtenir une solution validée par Dafny.
Généraliser pour deux arguments entiers relatifs.
method Mult(a: nat, b:nat) returns (m:nat)
    ensures m == a*b
{
  var x, y := 0, a;
  while y!= 0 
  ...  
  {
    x := x+b;
    y := y-1;
  }
  m := x;
}

Une méthode Somme pour ajouter deux entiers naturels

Considérer le code ci-dessous.
Déterminer un invariant de boucle, par exemple en décomposant la post-condition.
Déterminer un variant de boucle.
Compléter le code pour obtenir une solution validée par Dafny.
method Sum(a: nat, b: nat) returns (s: nat)
ensures s == a+b
{
  var x, y := a, b;
  while y != 0
        ...
  {
    x := x+1;
    y := y-1;
  }
  s := x;
}

une méthode de recherche linéaire pour les tableaux d'entiers

Compléter pour obtenir une solution validée par Dafny.
method LinearSearch(a:array<int>, key:int) returns (r:int)
  requires ...
  ensures 0 <= r ==> r < a.Length && a[r]==key
  ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != key
{
    ...
}

une méthode MaxArray pour les tableaux d'entiers

Ecrire et valider en Dafny une methode Max qui prend en entrée un tableau d'entiers non-vide et renvoie son plus grand élément. Formaliser la post-condition avec des ensures.
method MaxArray(a: array<int>) returns (max: int)
    requires 1 <= a.Length
    ensures ...
{
    ...
}

une fonction Sum_array pour les tableaux d'entiers

Ecrire en Dafny une fonction logique Sum_array(i,a) qui somme les éléments d'indice 0 à i inclus du tableau non-vide a.
Par récurrence finie sur i, montrer que cette fonction est correcte.
Quelle est la valeur de Sum_array(a.Length-1,a) ?
function Sum_array(i:int, a:array<int>): int
    requires 0 <= i < a.Length 
    ...

une méthode SumArray pour les tableaux d'entiers

Ecrire et valider en Dafny une methode SumArray qui prend en entrée un tableau d'entiers non-vide et renvoie la somme de ses éléments.
method SumArray(a: array<int>) returns (sum: int)
    requires 1 <= a.Length
    ensures sum == Sum_array(a.Length-1,a)
    ...

une méthode MinMaxSum pour les tableaux d'entiers

Ecrire et valider en Dafny une methode MinMaxSum qui prend en entrée un tableau d'entiers non-vide et renvoie son plus petit élément, son plus grand élément et la somme de ses éléments tout en garantissant les post-coditions ci-dessous :
method MinMaxSum(a:array<int>) returns (min:int, max:int, sum:int)
    requires 1 <= a.Length
    ensures a.Length * min <= sum <= a.Length * max
    ensures forall i :: 0 <= i < a.Length ==> a[i] <= max
    ensures exists i :: 0 <= i < a.Length  && a[i] == max
    ensures forall i :: 0 <= i < a.Length ==> a[i] >= min
    ensures exists i :: 0 <= i < a.Length  && a[i] == min
    ensures sum == Sum_array(a.Length-1,a)
    ...

une méthode de recherche dichotomique dans un tableau d'entiers trié

Considérer le code ci-dessous.
Exprimer la précondition et les post-conditions en langage naturel.
Exprimer les invariants et le variant de la boucle en langage naturel.
Compléter pour obtenir une solution validée par Dafny.
method BinarySearch(a:array<int>, key:int) returns (r:int)
    requires forall i,j :: 0 <= i < j < a.Length ==> a[i] <= a[j]
    ensures 0 <= r ==> r < a.Length && a[r]==key
    ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != key
{
    var lo, hi := 0, a.Length;
    while lo < hi 
        invariant 0 <= lo <= hi <= a.Length
        invariant forall i :: 0 <= i < lo ==> a[i] != key
        invariant forall i :: hi <= i < a.Length ==> a[i] != key
        decreases hi - lo
    {
    ...
    }
}

une méthode alternative de recherche dichotomique dans un tableau d'entiers trié

Cette méthode ne renvoie plus de valeurs négatives mais l'indice où la clé devrait être insérée dans le tableau pour qu'il reste trié. Donc les éléments a[i] du tableau situés à gauche de r sont tels que a[i] < key et les éléments a[j] du tableau situés à droite de r sont tels que a[j] >= key.
Exprimer la précondition et les post-conditions en langage naturel.
Exprimer les invariants et le variant de la boucle en langage naturel.
Compléter pour obtenir une solution validée par Dafny.
method BinarySearch_bis(a:array<int>, key:int) returns (r:int) 
    requires forall i,j :: 0 <= i < j < a.Length ==> a[i] <= a[j]
    ensures 0 <= r <= a.Length
    ensures r < a.Length ==> forall i,j :: 0 <= i < r <= j < a.Length ==> a[i] < key <= a[j]
    ensures r == a.Length ==> forall i :: 0 <= i < r ==> a[i] < key
{
    var lo, hi := 0, a.Length;
    while lo < hi 
        invariant 0 <= lo <= hi <= a.Length
        invariant forall i :: 0 <= i < lo ==> a[i] < key
        invariant forall i :: hi <= i < a.Length ==> key <= a[i] 
        decreases hi - lo
    {
        ...
    }
    return lo;
}

la méthode DutchFlag

Considérer le code ci-dessous. Le prédicat Below est-il Compléter pour obtenir une solution validée par Dafny.
datatype Color = Red | White | Blue
    
predicate Below(c: Color, d: Color)
    {
      c == Red || c == d || d == Blue
    }

method DutchFlag(a: array<Color>)
      modifies a
      ensures forall i,j :: 0 <= i < j < a.Length  ==>  Below(a[i], a[j])
      ensures multiset(a[..]) == multiset(old(a[..]))
    {
      var r, w, b := 0, 0, a.Length;
      while w < b
        invariant 0 <= r <= w <= b <= a.Length;
        invariant forall i :: 0 <= i < r ==> a[i] == Red
        invariant forall i :: r <= i < w ==> a[i] == White
        invariant forall i :: b <= i < a.Length ==> a[i] == Blue
        invariant multiset(a[..]) == multiset(old(a[..]))
      {   match a[w]
            case Red =>
            ...
            case White =>
            ...
            case Blue =>   
            ...
      }
    }
On pourra tester ce code comme suit :
method Main()
    {
      var a := new Color[3];
      a[0] := White;
      a[1] := Blue;
      a[2] := Red;
      assert a[..] == [White, Blue, Red];
      DutchFlag(a);
      assert Below(a[0], a[1]);
      assert Below(a[1], a[2]);
      assert a[..] == [Red, White, Blue];
    }

une méthode de tri d'un tableau de booléens

Considérer le contrat ci-dessous. Expliciter les deux post-conditions. Compléter le code pour obtenir une solution validée par Dafny.
method tri_tab_bool(a: array<bool>)
    modifies a
    ensures forall m,n :: 0 <= m < n < a.Length ==> (!a[m] || a[n])
    ensures multiset(a[..]) == multiset(old(a[..]))
{
    var lo, hi := 0, a.Length - 1;
    while (lo < hi)
    ...
}