method double(n : int) returns (r : int) requires n >= 0 ensures r == n * 2 { var x := 0; var y := 0; while (x < n) invariant 0 <= x <= n invariant y == x * 2 { x := x + 1; y := y + 2; } assert y == x * 2; return y; } method ex1(n : int) requires n >= 0 { var z := double(n); assert z == n * 2; } method double'(n : int) returns (r : int) requires n >= 0 ensures r == n * 2 { var y := 0; for x := 0 to n // for variabila := low to high ... (low <= high) // "variabila" ia valori de la low (inclusiv) la high (exclusiv) // invariant 0 <= x <= n (auto?) invariant y == x * 2 { y := y + 2; } return y; } /* for v := l to h invariant I { corp; } => var v := l; while (v < h) invariant l <= v <= h invariant I { corp; v := v + 1; } */ method double''(n : int) returns (r : int) requires n >= 0 ensures r == n * 2 { var y := 0; for x := n downto 0 // x merge de la n (exclusiv) pana la 0 (inclusiv) invariant y == (n - x) * 2 { y := y + 2; } return y; } method minSeq(s : seq) returns (r : int) requires |s| != 0 ensures forall j :: 0 <= j < |s| ==> r <= s[j] ensures exists j :: 0 <= j < |s| && r == s[j] { r := s[0]; for i := 1 to |s| invariant forall j :: 0 <= j < i ==> r <= s[j] invariant exists j :: 0 <= j < i && r == s[j] { if s[i] < r { r := s[i]; } } } method reverseSeq(s : seq) returns (r : seq) { r := []; for i := 0 to |s| { r := r + [ s[|s| - 1 - i] ]; // ineficient } } datatype List = Null | Cons(info : int, rest : List) method sum(l : List) returns (r : int) { r := 0; var p := l; while p != Null decreases p { r := r + p.info; p := p.rest; } } method minArray(a : array) returns (r : int) requires a.Length > 0 { r := a[0]; for i := 1 to a.Length { if a[i] < r { r := a[i]; } } } method reverseArray(a : array) returns (r : array) ensures r.Length == a.Length ensures forall ii :: 0 <= ii < a.Length ==> r[ii] == a[a.Length - 1 - ii] { r := new int [a.Length]; for i := 0 to a.Length invariant forall ii :: 0 <= ii < i ==> r[ii] == a[a.Length - 1 - ii] { r[i] := a[a.Length - 1 - i]; // in array pot scrie la o pozitie i } } method swap(a : array, i : int, j : int) requires 0 <= i < j < a.Length modifies a ensures a[i] == old(a[j]) ensures a[j] == old(a[i]) // ensures forall ii :: 0 <= ii < a.Length && ii != i && ii != j ==> a[ii] == old(a[ii]) ensures a[..i] == old(a[..i]) ensures a[i + 1..j] == old(a[i + 1..j]) ensures a[j + 1..] == old(a[j + 1..]) { var t := a[i]; a[i] := a[j]; a[j] := t; } method reverseArrayInPlace(a : array) modifies a // frame expression ensures forall ii :: 0 <= ii < a.Length ==> a[ii] == old(a[a.Length - 1 - ii]) { for i := 0 to a.Length / 2 invariant forall ii :: 0 <= ii < i ==> a[ii] == old(a[a.Length - 1 - ii]) invariant a[..][i..a.Length - i] == old(a[..])[i..a.Length - i] //invariant forall ii :: i <= ii < a.Length - i ==> a[ii] == old(a[ii]) invariant forall ii :: 0 <= ii < i ==> a[a.Length - 1 - ii] == old(a[ii]) { swap(a, i, a.Length - 1 - i); /* a[..i] ramane la fel a[i] si a[n - 1 - i] se interschimba a[i + 1 .. n - 1 - i] ramane la fel a[n - 1 - i..] ramane la fel */ } } method sumRecursive(l : List) returns (r : int) { match l { case Null => r := 0; case Cons(info, rest) => { var sum' := sumRecursive(rest); r := sum' + info; } } } method asdf() { var arr := new int[100]; var brr := arr; arr[3] := 7; assert brr[3] == 7; } method asdf1() { var arr := new int [100]; arr[7] := 13; var s : seq := arr[..]; assert s[7] == 13; }