Λύσεις Σειράς Ασκήσεων 5 Άσκηση 1 (α) Ακολουθεί η απόδειξη της προδιαγραφής (0) { A[X] = x A[Y] = y X Y (1) { A[Y] = y A[X] + Α[Υ] A[Y] = x X Y (2) A[X] := A[X] + A[Y]; (3) { A[Y] = y A[X] A[Y] = x X Y (4) { A[X] A[X] + A[Y] = y A[X] A[Y] = x X Y (5) A[Y] := A[X] A[Y]; (6) { A[X] A[Y] = y A[Y] = x X Y (7) A[X] := A[X] A[Y]; (8) { A[X] = y A[Y] = x X Y (9) { A[X] = y A[Y] = x Η συνθήκη X Y είναι απαραίτητο μέρος της προσυνθήκης, γιατί σε περίπτωση που τα Χ και Υ συμπίπτουν, τότε εκτέλεση των τριών αναθέσεων θα έχει ως αποτέλεσμα A[X] = 0 A[Y] = 0 και όχι τη δοθείσα μετασυνθήκη. Για παράδειγμα, παρατηρούμε ότι ο συμπερασμός (6 ) { A[X] A[Y] = y A[Y] = x (7 ) A[X] := A[X] A[Y]; (8 ) { A[X] = y A[Y] = x χωρίς τη συνθήκη X Y είναι λανθασμένος, αφού σε περίπτωση που Χ = Υ, η αντικατάσταση στην γραμμή (6 ) θα έπρεπε να δώσει και στο Α[Υ] την τιμή Α[Χ] Α[Υ]. (β) Ακολουθεί η απόδειξη όπου χρησιμοποιούμε ως αμετάβλητη συνθήκη την A[0] = A[1] = = A[i-1]= a i n και ως μεταβλητή έκφραση την n i.
{1 n {0 n {(A[0] = A[1] = = A[0-1]=a) 0 n i := 0; {(A[0] = A[1] = = A[i-1]=a) i n while (i < n){ {(A[0] = A[1]= = A[i-1]=a) i n i < n 0 n i = E 0 Αμ. Συνθ., Φρουρός, Μετ. Εκφ. {(A[0]= = A[i-1]=a) a = a i+1 n 0 n i 1< E 0 A[i] = a; {(A[0] = A[1] = = A[i] = a) i+1 n 0 n i 1< E 0 i := i+1; {(A[0] = A[1] = = A[i-1]=a) i n 0 n i < E 0 {(A[0] = A[1] = = A[i-1]=a) i n i n {A[0] = A[1] = = A[n-1]=a { i (0 i < n 1 A[i] A[i+1] ) Άσκηση 2 (α) (i) { p X:= E { p[e/x] Το αξίωμα είναι λάθος. Για παράδειγμα η χρήση του θα μας οδηγούσε στο συμπέρασμα ότι { Χ = Ε+1 X:= E { Ε = Ε+1 που είναι προφανώς λανθασμένο. (ii) { p[e/x] X:= E {p Το αξίωμα είναι ορθό: Αν κάποια συνθήκη p ισχύει μετά από την ανάθεση X:= E για τη μεταβλητή Χ τότε η συνθήκη αυτή θα πρέπει να ήταν αληθής και πριν από την ανάθεση για το Ε. (iii) { p X:= E { p X = E Το αξίωμα είναι λάθος. Για παράδειγμα η χρήση του θα μας οδηγούσε στο συμπέρασμα ότι { Χ = Ε+1 X:= E { Χ=Ε+1 Χ=Ε που είναι προφανώς λανθασμένο. (iv) { p X = E X:= E { p Το αξίωμα είναι ορθό. Προφανώς αν η εκτέλεση της ανάθεσης ξεκινήσει από μια κατάσταση όπου p και X = E, η ανάθεση δεν θα αλλάξει την κατάσταση του προγράμματος (το Χ είχε την τιμή Ε από την αρχή) επομένως η συνθήκη p θα συνεχίσει να ικανοποιείται.
(β) H εκφώνηση της άσκηση περιείχε τυπογραφικό λάθος. Η σωστή εκφώνηση είναι η εξής: Για οποιαδήποτε μεταβλητή Χ, ας γράψουμε Χ++ για την έκφραση η οποία υπολογίζεται ως την τιμή Χ+1 καθώς αυξάνει κατά 1 τη τιμή της μεταβλητής Χ. Για παράδειγμα, αν η μεταβλητή Χ έχει την τιμή 3 εκτέλεση της εντολής Υ := Χ++ έχει ως αποτέλεσμα τόσο το Υ όσο και το Χ να πάρουν την τιμή 4. Να εξηγήσετε γιατί εισαγωγή του πιο πάνω τύπου εκφράσεων στην γλώσσα while θα έχει ως αποτέλεσμα να χάσει την εγκυρότητά του το αξίωμα της ανάθεσης (διαφάνεια 9-13). Η εισαγωγή της έκφρασης αυτής στη γλώσσα έχει σαν αποτέλεσμα να χάσει την εγκυρότητά του το αξίωμα της ανάθεσης γιατί σε μία ανάθεση είναι δυνατόν να αλλάξουν ταυτόχρονα οι τιμές δύο και όχι μίας μεταβλητής, κάτι που δεν λαμβάνει υπόψη του ο κανόνας. Για παράδειγμα, ο υπάρχων κανόνας θα μας δώσει προδιαγραφές όπως την { Χ + 1 = Χ Υ:= Χ++ { Υ = Χ που προφανώς είναι λανθασμένη. (γ) O τελεστής X += E έχει οριστεί ως Χ := Χ+Ε. Κατάλληλο αξίωμα για την απόδειξη της ορθότητας προδιαγραφών που αφορούν τον τελεστή αυτό είναι το: {p[χ+e/x] X += E {p Το αξίωμα αυτό προκύπτει από το αξίωμα του τελεστή της ανάθεσης και τον ορισμό του τελεστή υπό μελέτη. (δ) Ακολουθεί αξίωμα για την εντολή ταυτόχρονης ανάθεσης: {p[e 1, E 2, E n / Χ 1, Χ 2,, Χ n ] Χ 1, Χ 2,, Χ n := E 1, E 2, E n {p Παρατηρούμε ότι ενώ η ασθενέστερη προσυνθήκη της ταυτόχρονης ανάθεσης Χ 1, Χ 2,, Χ n := E 1, E 2, E n είναι η p[e 1, E 2, E n / Χ 1, Χ 2,, Χ n ], η ασθενέστερη προσυνθήκη της ακολουθίας αναθέσεων Χ 1 := E 1 ; Χ 2 := E 2 ; ; Χ n := E n είναι η ( ((p[e n / Χ n ])[ E n-1 / Χ n-1 ]) )[ E 1 / Χ 1 ] Έτσι, για παράδειγμα, ισχύει ότι {3=3, Χ+1=5 Χ,Υ:=3, Χ+1 {X=3, Y=5 που μας δίνει ως ασθενέστερη προσυνθήκη την Χ=4 ενώ {Y+1=3, Υ+2 = 5 Χ:= Y+1; {X=3, Χ+1=5 Υ:=Χ+1 {X=3, Y=5 που μας δίνει ως ασθενέστερη προσυνθήκη την Y=2 Υ = 3 false.
Άσκηση 3 (α) H μεταβλητή a περιέχει την αρχική τιμή του πίνακα Α. (β) Ακολουθεί η απόδειξη όπου χρησιμοποιείται ως αμετάβλητη συνθήκη η η = k ((0 k < i) (A[k] = a[n k] A[n k] = a[k]) k ((i k n - i) A[k] = a[k]) {0 n i (i < n) A[i] = a[i]) { i (i < n) A[i] = a[i]) { k ((0 k < 0) (A[k] = a[n k] A[n k] = a[k]) k ((0 k n - 0) A[k] = a[k]) 0 + n = n i := 0; k ((i k n - i) A[k] = a[k]) i + n = n j := n; k ((i k n - i) A[k] = a[k]) i + j = n while (i < j) { k ((i k n - i) A[k] = a[k]) i + j = n i < j Φρουρός και Αμ. Συν. A[j] = a[n-i] A[i] = a[i] k ((i + 1 k n i 1) A[k] = a[k]) i + 1 + j 1 = n temp := A[i]; A[j] = a[n-i] temp = a[i] k ((i + 1 k n i 1) A[k] = a[k]) i + 1 + j 1 = n A[i] = A[j]; A[i] = a[n i] temp = a[i] k ((i + 1 k n i 1) A[k] = a[k]) i + 1 + j 1 = n A[j] = temp; { k ((0 k < i + 1) (A[k] = a[n k] A[n k] = a[k]) k ((i + 1 k n i 1) A[k] = a[k]) i+1+j 1= n i := i+1; k ((i k n - i) A[k] = a[k]) i + j 1 = n j := j-1; k ((i k n - i) A[k] = a[k]) i + j = n k ((i k n - i) A[k] = a[k]) i + j = n i j { k ( (0 k < n) A[k] = a[n k] ) { i ( (0 i < n) A[i] = a[n i] )
(γ) Μπορούμε να δείξουμε ότι το πρόγραμμα τερματίζει πάντοτε χρησιμοποιώντας ως μεταβλητή έκφραση την j δεδομένου ότι 0 n το οποίο υποθέτουμε ότι είναι αληθές ως μέρος της προσυνθήκης της προδιαγραφής. Άσκηση 4 (α) Ακολουθεί η απόδειξη μερικής ορθότητας της προδιαγραφής. Χρησιμοποιούμε ως αμετάβλητη συνθήκη την η = r p e = x n e 0 {x n = x n n 0 r := 1; {r x n = x n n 0 p := x; {r p n = x n n 0 e := n; {r p e = x n e 0 while e > 0 { {r p e = x n e 0 e > 0 {[e mod 2 0 r p 2 e div2+1 = x n e div 2 0 ] [e mod 2 = 0 r p 2 e div2 = x n e div 2 0] if (e mod 2) <> 0 {r p p 2 e div2 = x n e div 2 0 then r := r * p; {r p 2 e div2 = x n e div 2 0 {r p 2 e div2 = x n e div 2 0 p := p * p; {r p e div2 = x n e div 2 0 e := e div 2; {r p e = x n e 0 {r p e = x n e 0 e 0 {r = x n Αμ. Συν. και Φρουρός Προσυνθήκη if Κανόνας if (β) Ακολουθεί η απόδειξη ολικής ορθότητας της προδιαγραφής. Ως μεταβλητή έκφραση χρησιμοποιείται η e. {x n = x n n 0 r := 1; {r x n = x n n 0
p := x; {r p n = x n n 0 e := n; {r p e = x n e 0 while e > 0 { {r p e = x n e 0 0 e = Ε 0 Αμ. Συν., Μετ. Εκφρ. και Φρουρός {[e mod 2 0 r p 2 e div2+1 = x n 0 e div 2 < Ε 0 ] [e mod 2 = 0 r p 2 e div2 = x n 0 e div 2 < Ε 0 ] if (e mod 2) <> 0 {r p p 2 e div2 = x n 0 e div 2 < Ε 0 Προσυνθήκη if then r := r * p; {r p 2 e div2 = x n e div 2 0 {r p 2 e div2 = x n 0 e div 2 < Ε 0 Κανόνας if p := p * p; {r p e div2 = x n 0 e div 2 < Ε 0 e := e div 2; {r p e = x n 0 e < Ε 0 {r p e = x n e 0 e 0 {r = x n