diff --git a/4a1s/MFES/PL - Aula 9.md b/4a1s/MFES/PL - Aula 9.md index 55758aa..7c9ff54 100644 --- a/4a1s/MFES/PL - Aula 9.md +++ b/4a1s/MFES/PL - Aula 9.md @@ -86,3 +86,101 @@ end ``` +```c + +(* + The selection sort algorithm sorts an array + by successively placing in each position the + “next minimum” element, as follows: + + [40, 20, 10, 30, 60, 0, 80] + [0, 20, 10, 30, 60, 40, 80] + [0, 10, 20, 30, 60, 40, 80] + [0, 10, 20, 30, 60, 40, 80] + [0, 10, 20, 30, 60, 40, 80] + [0, 10, 20, 30, 40, 60, 80] + [0, 10, 20, 30, 40, 60, 80] + [0, 10, 20, 30, 40, 60, 80] + + 1. Complete the contract of function swap, writing + adequate pre- and post-conditions. + Recall that "length a" gives you the allocated length + of array a. + 2. Write a contract for function select. + Write also one or more loop invariants that allow + you to prove the correctness of the function. + Note that a loop variant is not required, since + "for" loops are bounded. + 3. Write one or more loop invariants that allow you to prove + the correctness of selection_sort_1. + You may need to modify the contract of select in order + for the loop invariant of selection_sort_1 to be proved. + 4. Finally, write the algorithm selection_sort_2, which does + not use the function select. It will have a nested loop; + write invariants for both loops and prove the correctness + of the algorithm. +*) + + +module SelectionSort + + use int.Int + use ref.Ref + use array.Array + use array.IntArraySorted + use array.ArrayPermut + use array.ArrayEq + + + + let swap (a: array int) (i: int) (j: int) + requires { 0 <= i< length a && 0 <= j< length a } + ensures { (old a)[i] = a[j] && (old a)[j] = a[i] } + ensures { forall k:int. 0<=k k<>i -> k<>j -> (old a)[i] = a[j]} + ensures { permut_all (old a) a } + = let v = a[i] in + a[i] <- a[j]; + a[j] <- v + + + + (* returns the index of a minimum of + the segment of a between indexes i and length a -1. + *) + let select (a: array int) (i: int) : int + requires { 0 <= i < length a} + ensures { i <= result < length a } + ensures { forall k:int. 0<=k a[result] <= a[k]} + = let ref min = i in + for j = i + 1 to length a - 1 do + invariant { i <= min < j } + invariant { forall k:int. i <= k < j -> a[min] <= a[k] } + if a[j] < a[min] then min <- j + done; + min + + + + let selection_sort_1 (a: array int) + ensures { sorted a } + ensures { permut_all (old a) a } + = for i = 0 to length a - 1 do + invariant { ... } + let min = select a i + in if min <> i then swap a min i + done + + + + + + let selection_sort_2 (a: array int) = + ensures { sorted a } + ensures { permut_all (old a) a } + ... + + +end + + +``` \ No newline at end of file