ΕΦΑΡΜΟΓΕΣ: ΟΙ ΑΛΓΕΒΡΙΚΕΣ ΠΡΟΔΙΑΓΡΑΦΕΣ Τμήματα. Στο προηγούμενο κομμάτι του κώδικα με τη λέξη κλειδί mod δηλώνουμε την αρχή μίας προδιαγραφής που θα βρίσκεται μέσα στο σώμα του mod, δηλαδή ανάμεσα από τα. Ο χαρακτήρας! ή * μετά από τη λέξη κλειδί mod δηλώνει ότι η προδιαγραφή που θα ακολουθήσει θα έχει είτε πρωταρχική είτε χαλαρή σημασιολογία (δηλαδή θα δηλώνει όλα τα μοντέλα που ικανοποιούν την προδιαγραφή και όχι μόνο τα ισομορφικά με το πρωταρχικό μοντέλο). Τύποι. Τα ονόματα των τύπων που ορίζει η προδιαγραφή δηλώνονται μέσα σε αγκύλες (π.χ. [SN at]). Ενα σύμβολο <, ανάμεσα στα ονόματα δύο τύπων δηλώνει ότι ο ένας είναι υποτύπος του άλλου. Τελεστές. Η λέξη κλειδί op ξεκινά τη δήλωση ενός τελεστή του οποίου το πεδίο ορισμού δηλώνεται πριν την άνω και κάτω τελεία και ο τύπος του συνόλου τιμών μετά το βέλος. Συνήθως τον τύπο του συνόλου τιμών μαζί με αυτόν του πεδίου ορισμού τους ονομάζουμε τάξη (rank) του τελεστή. Η γλώσσα υποστηρίζει την δήλωση διαφόρων ιδιοτήτων των τελεστών μέσα σε {} με τη χρήση διαφόρων λέξεων κλειδιών, για παράδειγμα η δήλωση ότι ο τελεστής είναι αντιμεταθετικός γίνεται χρησιμοποιώντας τη λέξη κλειδί assoc. Εξισώσεις. Η λέξη κλειδί eq σηματοδοτεί την έναρξη του ορισμού μίας εξίσωσης, στην οποία το δεξί της μέρος δηλώνεται πριν από το σύμβολο = ενώ το αριστερό μετά από αυτό. Το τέλος της δήλωσης μιας εξίσωσης σηματοδοτείται από μία τελεία.. Μεταβλητές. Οι μεταβλητές δηλώνονται χρησιμοποιώντας τη λέξη κλειδί var ακολουθούμενη από το όνομα της μεταβλητής, μία άνω και κάτω τελεία και το τύπο της μεταβλητής. Είναι δυνατόν να συμπτύξουμε τους ορισμούς πολλών μεταβλητών ίδιου τύπου σε μία γραμμή χρησιμοποιώντας τη λέξη κλειδί vars. Ετσι για παράδειγμα η έκφραση vars N M : SNat σηματοδοτεί τη δήλωση δύο μεταβλητών με ονόματα N, M που είναι τύπου SN at. Ακόμα είναι δυνατό να χρησιμοποιήσουμε σε μία εξίσωση μεταβλητές που δεν έχουν οριστεί προηγουμένως, απλά δηλώνοντας το τύπο και το όνομα της μεταβλητής μέσα στην εξίσωση. Αυτή η μεθοδολογία καλείται επιτόπου 109
δήλωση μεταβλητών. Ετσι οι ακόλουθες δύο εξισώσεις έχουν ταυτόσημη σημασιολογία: var N : SNat. eq (s(n) = 0) = false. και eq (s(n: SNat) = 0) = false. Εξισώσεις υπό συνθήκη. Ακόμα η δήλωση μίας υπό-συνθήκης εξίσωσης γίνεται με τη χρήση της κωδικής λέξης ceq, που ακολουθείται από μία εξίσωση στο τέλος της οποίας βρίσκεται μία έκφραση της μορφής if P, όπου P είναι κάποιο κατηγόρημα. Ετσι για παράδειγμα η δήλωση ceq (S(M) = S(N)) = true if (M = N) ορίζει ότι ο όρος S(N) είναι ίσος με τον όρο S(M) αν οι όροι M, N είναι ίσοι (όπου Μ,Ν μεταβλητές του ίδιου τύπου). Ισότητες. Τέλος στη γλώσσα ορίζονται δύο ειδών ισότητες μέσω δύο κατηγορημάτων. Ο πρώτος τελεστής ισότητας ορίζεται ως =, ενώ ο δεύτερος ως ==. Και οι δύο τελεστές επιστρέφουν true αν τα δύο τους ορίσματα μπορούν να αναγραφούν (με βάση το σύστημα αναγραφής της γλώσσας) στο ίδιο όρο. Αλλά ο όρος L : S == L : S επιστρέφει false αν ο L αναγράφεται σε t1 και ο L σε t2 ενώ ο ορός L : S = L : S θα επιστρέψει t1 = t2. Σχόλια. Τέλος οι γραμμές που αρχίζουν με αποτελούν σχόλια και αγνοούνται από τη μηχανή. Θα εξετάσουμε τώρα εν συντομία πώς η γλώσσα υποστηρίζει τα διάφορα χαρακτηριστικά που αναφέραμε προηγουμένως. Τμηματικό σύστημα προδιαγραφών (Module System). Οι αρχές του τμηματικού συστήματος της Caf eobj κληρονομούνται από την OBJ και βασίζονται σε ιδέες οι οποίες για πρώτη φορά εμφανίστηκαν στη γλώσσα Clear και κυρίως στη θεωρία θεσμών. Το τμηματικό σύστημα της γλώσσας μας επιτρέπει τη χρήση διαφόρων ειδών εισαγωγής άλλων προδιαγραφών στη θεωρία που ορίζουμε (μέσω των λέξεων κλειδιών pr, ex,... ) και παραμετρικού προγραμματισμού: πολλαπλές παραμέτρους σε μία προδιαγραφή views για την αρχικοποίηση των παραμέτρων Για παράδειγμα ο παρακάτω κώδικας ορίζει μία παραμετρική προδιαγραφή ενός συνόλου: mod* Elt{ [Elt] op _=_ : Elt Elt -> Bool {comm} eq (E:Elt = E) = true. } mod! SET(D :: Elt) { [Elt.D < Set] op : Set Set -> Set {assoc comm} 110
pred _in_ : Elt.D Set vars X Y : Elt.D var B : Set eq X in Y = (X = Y). eq X in Y B = (X = Y) or (X in B). } view Elt2Nat from EQL-Elt to NAT { sort Elt -> Nat, vars X Y : Elt, op (X = Y) -> (X >= Y) and (X <= Y) } Η πρώτη προδιαγραφή (ELT) ορίζει με χαλαρή σημασιολογία μία πολύ απλή δομή δεδομένων, αυτή του τυχαίου στοιχείου. Στη συνέχεια ορίζεται η παραμετρική προδιαγραφή του συνόλου από αυτά τα τυχαία στοιχεία (SET). Η παραμετρική προδιαγραφή δίνεται μέσω της έκφρασης SET(D :: EQL-Elt) η οποία δηλώνει ότι η προδιαγραφή SET έχει παράμετρο D που είναι μία θεωρία για την ELT. Στη συνέχεια μπορούμε να αρχικοποιήσουμε αυτή τη παράμετρο με μία άλλη θεωρία που επεκτείνει την ELT όπως η θεωρία για τους ακεραίους NAT. Αυτό επιτυγχάνεται μέσω του ορισμού ενός μορφισμού τον οποίο καλούμε Elt2Nat ο οποίος απεικονίζει το τύπο Elt στον Nat και το τελεστή = της ELT στη έκφραση (X >= Y) and (X <= Y). Σύστημα τύπων. Το σύστημα τύπων της Caf eobj είναι βασισμένο στην άλγεβρα με πολλούς τύπους και διάταξη (ΑΤΔ) έτσι επιτρέπει τον ορισμό υποτύπων. Αυτό προσφέρει αυστηρό έλεγχο των τύπων της προδιαγραφής καθώς και μία μεθοδολογία για τον χειρισμό σφαλμάτων βασισμένη σε αυτό. Ακόμα αυτό το σύστημα επιτρέπει συντακτική ευελιξία στη γλώσσα συγκρίσιμη με αυτή των γλωσσών χωρίς τύπους ενώ ταυτόχρονα διατηρεί όλα τα πλεονεκτήματα των τύπων. Η Caf eobj δεν επιτρέπει τον απευθείας ορισμό μερικών τελεστών. Για να μπορέσουμε να ορίσουμε τέτοιους τελεστές μπορούμε να χρησιμοποιήσουμε το σύστημα των υποτύπων που μας προσφέρει η γλώσσα. Για παράδειγμα αν επιθυμούσαμε να ορίσουμε μια προδιαγραφή για τη δομή της στοίβας στην οποία δεν επιτρέπεται η εξαγωγή στοιχείου από την κενή στοίβα (δηλαδή ο τελεστής pop να είναι μερικά ορισμένος), τότε θα μπορούσαμε να το επιτύχουμε με την παρακάτω προδιαγραφή: mod* Elt{ [Elt < EltErr] op err : -> EltErr op _=_ : Elt Elt -> Bool {comm} eq (E:Elt = E) = true. eq (E:Elt = err) = false. 111
} mod! Stack(D :: Elt) { pr(eql) [Elt.D <EltErr < Stack < StackErr] op push : Stack Elt.D -> Stack {constr} op pop : Stack -> StackErr op head : Stack -> Elt.D op empty : -> Stack -- vars X Y : Elt.D var S : Stack var B : Set -- eq pop(empty) = err. ceq pop(push(s,x)) = err if (S = empty). } Οπου EltErr είναι ένας υπερτύπος του Elt και δηλώνει ένα λάθος στοιχείο. Ακόμα err είναι μία σταθερά αυτού του λάθος τύπου που είναι διαφορετική από κάθε στοιχείο τύπου Elt. Χρησιμοποιώντας αυτά μπορούμε να ορίσουμε τον pop σαν μερικό τελεστή δηλώνοντας με την εξίσωση eq pop(empty) = err και ceq pop(push(s,x)) = err if (S = empty). οτι η εφαρμογή του σε μία κενή στοίβα επιστρέφει ακριβώς αυτό το λάθος στοιχείο. Βεηα ιουραλ Σπεςιφιςατιονς. Η CafeOBJ υποστηρίζει απευθείας τις συμπεριφοριακές προδιαγραφές και την θεωρία αποδείξεών τους που αναπτύξαμε στη προηγούμενη ενότητα μέσω ειδικών κατασκευασμάτων της γλώσσας. Πιο συγκεκριμένα ένας κρυφός τύπος ορίζεται μέσα σε αγκύλες περιβαλόμενες από αστερίσκους, δηλαδή *[hiddensortnames]*. Η σημασιολογία ενός τέτοιου τύπου είναι αυτή της κρυφής άλγεβρας δηλαδή αυτή των καταστάσεων ενός συστήματος. Οι συμπεριφοριακοί τελεστές (behavioral operations) που όπως είπαμε περιέχουν στο πεδίο ορισμού τους ένα κρυφό τύπο ορίζονται με τη λέξη κλειδί bop. Αυτοί οι τελεστές κατά αντιστοιχία με τη κρυφή άλγεβρα μπορούν να διαχωριστούν σε παρατηρήσεις όταν ο τύπος του συνόλου τιμών τους είναι ορατός και σε πράξεις όταν είναι κρυφός. Η CafeOBJ διευκολύνει τις αποδείξεις που γίνονται με τη μέθοδο της συνεπαγωγής ορίζοντας απευθείας μία σχέση ισοδυναμίας σε κάθε κρυφή προδιαγραφή η οποία συμβολίζεται ώς = =. Στη συνέχεια η μηχανή της γλώσσας προσπαθεί να αποδείξει αυτόματα ότι η σχέση αυτή είναι Γ-διατηρητική (χρησιμοποιώντας ώς Γ όλους τους συμπεριφοριακούς τελεστές) και ενημερώνει για το αποτέλεσμα της απόδειξης. Αν η 112
μηχανή επιτύχει στην απόδειξή της τότε η σχέση = = μπορεί να χρησιμοποιηθεί σαν κρυφή ισοδυναμία για την απόδειξη συμπεριφοριακών ιδιοτήτων με τη μέθοδο της συνεπαγωγής. Για παράδειγμα ο ακόλουθος κώδικας αποτελεί μία συμπεριφοριακή προδιαγραφή μίας δομής στοίβας ακεραίων mod* IntStack{ pr(eql + NAT) *[istack]* -- operations bop head : istack -> Nat. bop push : istack Nat -> istack. bop pop : istack -> istack. -- initial state bop empty : -> istack -- variables var S : istack. vars N M : Nat -- eq head(push(s, N)) = N. ceq pop(s) = empty if S = empty. } Εκτός από τα ειδικά κατασκευάσματα η Caf eobj υποστηρίζει τις συμπεριφοριακές προδιαγραφές και την απόδειξη ιδιοτήτων γι αυτές με διάφορες άλλες μεθοδολογίες και συγκεκριμένα κυρίως μέσω της συμπεριφοριακής αναγραφής (behavioral rewriting). Δηλαδή η μηχανή υλοποιεί τους κανόνες αναγραφής που αναπτύξαμε στη προηγούμενη ενότητα (ο πιο σημαντικός από τους οποίους είναι η χρήση του κανόνα της ισοδυναμίας μόνο σε συμπεριφοριακά διατηρητικούς τελεστές) εξασφαλίζοντας έτσι την ορθότητα των αποδείξεων που δημιουργούνται χρησιμοποιώντας το σύστημα αναγραφής. Η χρήση της Caf eobj έχει δείξει ότι οι συμπεριφοριακές προδιαγραφές μπορούν να εφαρμοστούν αποτελεσματικά και σαν αντικειμενοσταφής εναλλακτική για τις παραδοσιακές προσανατολισμένες στα δεδομένα αλγεβρικές προδιαγραφές. Μάλιστα, τα μέχρι στιγμής αποτελέσματα δείχνουν ότι μία τέτοια προσέγγιση μπορεί να μειώσει δραματικά το κόστος της προδιαγραφής των συστημάτων και της επαλήθευσής τους. Προδιαγραφές βασισμένες σε λογική αναγραφής. Η λογική του συστήματος αναγραφής της Caf eobj βασίζεται στη λογική αναγραφής (RW L) του M eseguer η οποία δίνει μία μη τετριμμένη επέκταση στις παραδοσιακές αλγεβρικές προδιαγραφές επιτρέποντας έννοιες όπως ο παραλληλισμός των υπολογισμών. Η RW L ενσωματώνει πολλά διαφορετικά μοντέλα παραλληλισμού με ένα απλό και φυσικό τρόπο 113
και έτσι παρέχει στη Caf eobj ευρύ πεδίο εφαρμογών. Η γλώσσα επιτρέπει την α- πόδειξη ιδιοτήτων για την ύπαρξη μεταβάσεων ανάμεσα από καταστάσεις συστημάτων μέσω του τελεστή ==> ο οποίος ενσωματώνει τη θεωρίας αποδείξεων της RW L με την εξισωτική λογική. Συστήματα Παρατηρήσεων Μεταβάσεων (Observational Transition Systems) - Αναλλοίωτες ιδιότητες (Invariant properties). Τα Συστήματα Παρατηρήσεων Μεταβάσεων (ΣΠΜ) αποτελούν μία γνήσια υπό-κλάση των συμπεριφοριακών προδιαγραφών. Παρόλ αυτά είναι ικανά να περιγράψουν μία πληθώρα προβλημάτων και για αυτό το λόγο έχουν χρησιμοποιηθεί πολύ στη βιβλιογραφία. Πιο συγκεκριμένα, υποθέτουμε ότι υπάρχει ένας χώρος καταστάσεων, τον οποίο συνήθως συμβολίζουμε με Υ. Ακόμα υποθέτουμε ότι όλοι οι τύποι δεδομένων που θα χρειαστεί να χρησιμοποιήσουμε έχουν οριστεί εκ των προτέρων συμπεριλαμβανομένης και της ισότητας μεταξύ των στοιχείων του ίδιου τύπου δεδομένων. Ενα σύστημα περιγράφεται σαν ένα ΣΠΜ παρατηρώντας από κάποιο εξωτερικό ως προς το σύστημα σημείο την κατάσταση του. Δηλαδή, το μόνο που μπορούμε να παρατηρήσουμε είναι οι τιμές κάποιων πειραμάτων που μπορούμε να διεξάγουμε και το πώς αυτές οι τιμές αλλάζουν όταν εφαρμοστούν οι κανόνες μετάβασης του συστήματος. Η αντιστοιχία με τις συμπεριφοριακές προδιαγραφές είναι προφανής, τα διάφορα πειράματα αντιστοιχούν στους τελεστές παρατήρησης ενώ οι κανόνες μετάβασης στις μεθόδους. Τυπικά ένα ΣΠΜ ορίζεται ώς μία τριάδα, ΣΠΜ S =< O, I, T > όπου: O, είναι ένα σύνολο από πειράματα, κάθε τέτοιο πείραμα, o O, ορίζει μία συνάρτηση o : Y D όπου D είναι κάποιος τύπος δεδομένων που μπορεί να είναι διαφορετικός για κάθε πείραμα. Δεδομένου τώρα ενός ΣΠΜ και δύο καταστάσεων u 1, u 2 Y η ισότητα ανάμεσα σε αυτές τις δύο καταστάσεις, συμβολίζεται ως u 1 = S u 2, και ορίζεται ως o O.o(u 1 ) = D o(u 2 ) όπου = D συμβολίζει την ισότητα ανάμεσα σε όρους του ίδιου τύπου δεδομένων D. I, αποτελεί ένα υποσύνολο του συνόλου όλων των πιθανών καταστάσεων του συστήματος, Y, το οποίο συνήθως ονομάζουμε σύνολο των αρχικών καταστάσεων. T, ένα σύνολο από υπό-συνθήκη κανόνες μετάβασης. Κάθε τέτοιος κανόνας τ T ορίζει μία συνάρτηση πάνω στις κλάσεις ισοδυναμίας του χώρου των καταστάσεων με βάση το ΣΠΜ, (Y/ =S ). Στη συνέχεια με τ(u) θα συμβολίζουμε οποιοδήποτε από τα στοιχεία του τ[u], δηλαδή όλες τις ισοδύναμες με τη u καταστάσεις στις οποίες εφαρμόζουμε τον κανόνα μετάβασης τ. Τότε η τ(u) θα καλείται η διάδοχος κατάσταση της u με βάση τον κανόνα τ. Ακόμα μαζί με κάθε κανόνα μετάβασης ορίζεται και μία συνθήκη που τη 114
συμβολίζουμε συνήθως ως c-τ η οποία είναι στη πραγματικότητα ένα κατηγόρημα πάνω στις καταστάσεις του Y τέτοιο ώστε να ισχύει ότι τ(u) = S u αν c-τ(u). Ενα ΣΠΜ μπορεί να περιγραφεί με φυσικό τρόπο στη Caf eobj. Τα πειράματα α- ναπαριστώνται από τελεστές παρατήρησης στη Caf eobj και οι κανόνες μετάβασης με συμπεριφοριακούς τελεστές της Caf eobj με κρυφό τύπο. Συνήθως οι παρατηρήσεις αυτές και οι κανόνες μετάβασης είναι παραμετρικοί, και σε αυτή τη περίπτωση υποθέτοντας ότι υπάρχουν D k με k = i 1,..., i m, j 1,..., j n τους συμβολίζουμε ως o i1,..., o im και τ j1,..., τ jn όπου m, n 0 αντίστοιχα. Για παράδειγμα ένα πείραμα που επιστέφει το στοιχείο στη θέση n N ενός πίνακα θα μπορούσε να συμβολιστεί ως o n και ένας κανόνας μετάβασης που αυξάνει κατά x την τιμή του στοιχείο αυτό θα μπορούσε να συμβολιστεί ως inc n,x. Δεδομένου τώρα ενός ΣΠΜ θα αποκαλούμε εκτέλεση μια άπειρη ακολουθία από καταστάσεις u 0,..., u n,... οι οποίες ικανοποιούν τις ακόλουθες συνθήκες: (Αρχικοποίηση) u 0 I (Διαδοχή) για κάθε i {0, 1,... } u i+1 = S τ(u i ), για κάποιο τ T, δηλαδή όλες οι καταστάσεις προκύπτουν από την προηγούμενη κατάσταση της ακολουθίας εφαρμόζοντας κάποιο κανόνα μετάβασης. Θα λέμε ότι μία κατάσταση είναι προσβάσιμη (reachable) ανν εμφανίζεται ως μέρος κάποιας εκτέλεσης του S. Με R S θα συμβολίζουμε το σύνολο όλων των προσβάσιμων καταστάσεων του S. Μια ιδιότητα θα καλείται αναλλοίωτη (invariant), όσο αφορά το S, ανν ισχύει για όλες τις προσιτές καταστάσεις του S. Τυπικά αυτό συμβολίζεται ώς: invariant(p) ανν ( u I, p(u)) και ( u R S τ T.p(u) p(τ(u))) Ας δούμε τώρα πώς περιγράφουμε ένα ΣΠΜ στην CafeOBJ. Το σύνολο των καταστάσεων περιγράφεται από ένα κρυφό τύπο, H. Ενα πείραμα o i1,...,i m O όπως είπαμε με ένα τελεστή παρατήρησης. Υποθέτουμε ότι οι τύποι δεδομένων που θα χρειαστούμε οι D i1,... D im και D έχουν προδιαγραφεί σαν πρωταρχικές άλγεβρες έτσι ώστε να υπάρχουν οι αντίστοιχοι ορατοί τύποι V i1,... V im και V. Τότε: Ο τελεστής της CafeOBJ που αντιστοιχεί στο πείραμα o i1,...,i m ορίζεται ως, βοπ ο : Η V i1... V im -> V κάθε αρχική κατάσταση u I αναπαρίσταται από μία κρυφή σταθερά op u init : > H. Αν η τιμή του o i1,...,i m στην αρχική κατάσταση u ορίζεται ώς f(i 1,..., i m ) τότε αυτό ορίζεται στην CafeOBJ ως o(u i nit, X i1,..., X im ) = f(x i1,... X im ) όπου X i1,..., X im είναι μεταβλητές τύπων V i1,... V im α- ντίστοιχα ορισμένες στη CafeOBJ. 115
ένας κανόνας μετάβασης τ j1,...,j n αναπαρίσταται από μία μέθοδο στη CafeOBJ, bop a : H V j1..., V jn > H. Αν ένας κανόνας μετάβασης εφαρμοστεί σε μία κατάσταση όπου η συνθήκη του ισχύει η τιμή ενός πειράματος του ΣΠΜ, έστω o i1,...,i m, μπορεί να αλλάξει το οποίο περιγράφεται στην CafeOBJ με μία εξίσωση, ceq o(a(u, X j1,..., X jn )), (X i1,..., X im ) = c a(u, X j1,..., X jn, X i1, X im ) if c a(u, X j1,...,x jn ). Τέλος αν ένας κανόνας a εφαρμοστεί σε μία κατάσταση στην οποία δεν ισχύει η συνθήκη του τότε η νέα κατάσταση πρέπει να είναι ισοδύναμη με τη προηγούμενη όσο αφορά την = S. Αυτό δηλώνεται στη CafeOBJ πάλι με μία εξίσωση, ceqa(u, X j1,...,x jn ) = u if not c-α(υ,x j1,..., X jn ). Η μέθοδος των Proof Scores. Η επαλήθευση ότι ο σχεδιασμός ενός συστήματος (ΣΠΜ) πληρεί κάποιες ιδιότητες ασφαλείας τις περισσότερες φορές ανάγεται στην απόδειξη οτι η προδιαγραφή ικανοποιεί ένα σύνολο από αναλλοίωτες ιδιότητες (invariant properties), δηλαδή ιδιότητες που ισχύουν σε κάθε κατάσταση του συστήματος. Ετσι η απόδειξη αναλλοίωτων ιδιοτήτων έχει μελετηθεί εκτενώς. Σε αυτή την ενότητα θα παρουσιάσουμε μία ολοκληρωμένη μεθοδολογία για την απόδειξη τέτοιων ιδιοτήτων για συμπεριφοριακές προδιαγραφές ορισμένες με όρους της Cafe- OBJ, που ονομάζεται Proof Scores [24] [25] [26] [27] [28] [29]. Η μεθοδολογία των Proof Scores χαρακτηρίζεται ως διαδραστική μεταξύ του χρήστη και του υπολογιστή. Ο χρήστης γράφει με κατάλληλο τρόπο το πλάνο της απόδειξης και ο υπολογιστής την εκτελεί αναλαμβάνοντας όλους τους κουραστικούς υπολογισμούς και απαντάει με true ή false ανάλογα με το αν επιτυγχάνει το πλάνο της απόδειξης. Σε αντίθεση με τα πλήρως αυτοματοποιημένα συστήματα αποδείξεων αυτός ο τρόπος έχει σαν πλεονεκτήματα ότι: επιστρέφει επαρκείς πληροφορίες σε περίπτωση που κάποιο πλάνο αποτύχει, έναντι ενός απλού ναι ή όχι που επιστρέφουν τα αυτοματοποιημένα συστήματα αποδείξεων επιτρέπει την καλύτερη κατανόηση του συστήματος (της προδιαγραφής) σε περίπτωση που δεν ικανοποιεί τις ιδιότητες που μας ενδιαφέρον, γεγονός που κάνει τον επανασχεδιασμό του πιο εύκολο. Για παράδειγμα ας υποθέσουμε ότι επιθυμούμε να αποδείξουμε ότι η ιδιότητα pred1(s, x1) η οποία είναι γραμμένη σε όρους της Caf eobj είναι αναλλοίωτη για μία προδιαγραφή ΣΠΜ γραμμένη πάλι σε όρους της CafeOBJ, όπου s είναι μια ελεύθερη μεταβλητή τύπου των καταστάσεων του συστήματος και x1 ένα σύνολο από ελεύθερες πάλι μεταβλητές. Συχνά δεν είναι δυνατόν να καταφέρουμε την απόδειξη ε- νός κατηγορήματος χρησιμοποιώντας μόνο τους κανόνες αναγραφής που έχουμε αναπτύξει. Εξαιτίας όμως της δομή μίας ΣΠΜ μπορούμε να χρησιμοποιήσουμε επαγωγή 116
(induction) στις καταστάσεις για να δείξουμε ότι η ιδιότητα pred1(s, x1) είναι αναλλοίωτη. Αυτό γίνεται δείχνοντας ότι η ιδιότητα ισχύει για κάθε αρχική κατάσταση, u I.pred(u, x1), και στη συνέχεια υποθέτοντας ότι ισχύει για την τυχαία κατάσταση s δείχνουμε οτι ισχύει για κάθε διαδοχική κατάσταση για κάθε κανόνα μετάβασης, τ T.pred1(s, x1) pred1(τ(s), x1). Τις περισσότερες φορές όμως η απόδειξη του pred1(s, x1) χρησιμοποιώντας μόνο επαγωγή είναι αδύνατη. Παρόλ αυτά είναι δυνατή η απόδειξη ότι το pred1 μαζί με άλλα n-1 κατηγορήματα είναι αναλλοίωτα για τη ΣΠΜ προδιαγραφή (αυτά τα κατηγορήματα θα τα συμβολίζουμε με pred2(s, x2),..., predn(s, xn)). Για παράδειγμα έστω ότι κατά την επαγωγική απόδειξη του pred1(s, x1) προσπαθούμε να δείξουμε ότι ισχύει το επαγωγικό βήμα για τον κανόνα μετάβασης τ, δηλαδή ότι: pred1(s, x1) pred1(τ(s), x1). Πολλές φορές η απόδειξη αυτή είναι αδύνατη, αλλά παρόλ αυτά μπορούμε να αποδείξουμε τη διατήρηση της ιδιότητας από το κανόνα μετάβασης χρησιμοποιώντας μία πιό ισχυρή υπόθεση για παράδειγμα: pred1(s, x1) predi(s, xi) predj(s, xj) pred1(τ(s), x1), όπου 1 i, j n. Επιπλέον είναι δυνατόν η απόδειξη των επιπλέον κατηγορημάτων να είναι επίσης αδύνατη χωρίς τη χρήση των υπολοίπων. Δηλαδή να μπορούμε να δείξουμε μόνο ότι: pred1(s, x1) predi(s, xi) predj(s, xj) predi(τ(s), xi), όπου 1 i, j n. Θα συμβολίζουμε αυτή την ισχυροποιημένη υπόθεση ώς SH i. Ακόμα για την απόδειξη των pred1(s, x1) predi(s, xi) predj(s, xj) pred1(τ(s), x1), τις περισσότερες φορές χρειάζεται να διακρίνουμε περιπτώσεις (Case Splitting). Δηλαδή, η κατάσταση s να διακριθεί σε l υποκαταστάσεις οι οποίες να ορίζονται από τις φόρμουλες case k, 1 k l ώστε να είναι εξαντλητικές, δηλαδή: (case 1 case l ) = true. Με αυτό το τρόπο η απόδειξη του pred1(s, x1) predi(s, xi)... predj(s, xj) predi(τ(s), xi) σπάει σε l αποδείξεις: case i 1 pred1(s, x1) predi(s, xi) predj(s, xj) predi(τ(s), xi)... case i l pred1(s, x1) predi(s, xi) predj(s, xj) predi(τ(s), xi) Δηλαδή αντί να δείξουμε ότι η ιδιότητα pred1(s, x1) είναι αναλοίωτη δείχνουμε ότι η ιδιότητα pred1(s, x1) pred2(s, x2) predn(s, xn) είναι αναλλοίωτη. Η μεθοδολογία αυτή καλείται ταυτόχρονη επαγωγή (Simultaneous Induction) και είναι η κύρια μεθοδολογία απόδειξης μίας αναλλοίωτης ιδιότητας για μια ΣΠΜ/CafeOBJ προδιαγραφής. Προφανώς αν μπορούμε να αποδείξουμε τη σύζευξη τότε ισχύει και το pred1(s, x1). Τα κατηγορήματα pred2(s, x2),..., predn(s, xn)) θα τα λέμε λήμματα. Ακόμα θα συμβολίσουμε με pred(s, x1,..., xn) τη σύζευξη των κατηγορημάτων. Υλοποίηση των Proof Scores στην CafeOBJ. Θα δούμε τώρα πώς μπορούμε να ορίσουμε μία τέτοια απόδειξη στη Caf eobj. Πρώτα ορίζουμε ένα module το οποίο συνήθως το καλούμε IN V όπου τα κατηγορήματα εκφράζονται με όρους της CafeOBJ. 117
module INV{ op inv1 : H V1 -> Bool op invn : H Vn -> Bool eq inv1(w,x1) = pred1(w,x1). eq invn(w,xn) = predn(w,xn). } όπου W είναι μια CafeOBJ μεταβλητή του τύπου ΣΠΜ και Xn ένα σύνολο από Caf eobj μεταβλητές για τις xi. Τέλος ο όρος predn(w, Xi) εκφράζει σε όρους της γλώσσας το κατηγόρημα predn(s, xn). Επίσης στο module δηλώνουμε σταθερές x i, (i = 1,..., n) που είναι του ίδιου τύπου με τα Xi. Στο σώμα μίας απόδειξης μία σταθερά χρησιμοποιείται για να δηλώσει ένα τυχαίο αντικείμενο του συγκεκριμένου τύπου. Για παράδειγμα αν δηλώσουμε μια σταθερά τύπο Nat την x η x μπορεί να χρησιμοποιηθεί για να σηματοδοτήσουμε ένα τυχαίο φυσικό αριθμό. Μέσω αυτών των σταθερών και χρησιμοποιώντας κατάλληλες εξισώσεις μπορούμε να κάνουμε τον διαχωρισμό των καταστάσεων που αναφέραμε προηγουμένως. Για παράδειγμα αν θέλουμε να θεωρήσουμε δύο καταστάσεις στις οποίες ένας τυχαίος φυσικός είναι μεγαλύτερος από το μηδέν στη μία και μικρότερος, ίσος στην άλλη θα μπορούσαμε να το δηλώσουμε με τις ακόλουθες εξισώσεις: eq (x > 0) = true. eq (x <= 0) = true. Είμαστε τώρα σε θέση να περιγράψουμε το proof score του i-οστού κατηγορήματος. Εστω ότι init είναι μια σταθερά η οποία συμβολίζει μια τυχαία αρχική κατάσταση του συστήματος. Το μόνο που χρειάζεται να κάνουμε για να δείξουμε ότι το κατηγόρημα predi(s, xi) ισχύει σε κάθε αρχική κατάσταση είναι να γράψουμε τον ακόλουθο κώδικα στη Caf eobj: open INV red invi(init, xi). close Στη συνέχεια γράφουμε ένα module, το οποίο συνήθως το συμβολίζουμε με IST EP, στο οποίο δηλώνουμε δύο σταθερές την s και την s, οι οποίες αντιστοιχούν σε μία τυχαία κατάσταση του ΣΠΜ και στην διαδοχική της, δηλαδή στην επόμενη κατάσταση από την s μετά από την εφαρμογή κάποιου κανόνα μετάβασης. Τα κατηγορήματα που πρέπει να αποδείξουμε στην περίπτωση αυτή είναι: op istep1 : V1 -> Bool op istepn : Vn -> Bool 118
eq istep1(x) = inv1(s,x1) implies inv1(s,x1). eq istepn(x) = invn(s,xn) implies invn(s,xn). Σε κάθε περίπτωση επαγωγής (δηλαδή για κάθε κανόνα μετάβασης) η κατάσταση συνήθως διαχωρίζεται όπως είπαμε σε υποκαταστάσεις. Για παράδειγμα έστω ότι προσπαθούμε να αποδείξουμε ότι κάποιος κανόνας μετάβασης διατηρεί το κατηγόρημα i. Συνήθως λοιπόν διαχωρίζουμε την κατάσταση σε l-υποκαταστάσεις, case i με 1 i l. Τότε, ο ακόλουθος κώδικας στη CafeOBJ δείχνει ότι η υποκατάσταση case i για τον κανόνα μετάβασης a διατηρεί την ιδιότητα: open ISTEP Declare constants denoting arbitrary objects. Declare equations denoting casei. Declare equations denoting facts if necessary. eq s = a(s, y). red istepi(xi). close όπου y είναι μία λίστα σταθερών οι οποίες χρησιμοποιούνται ως ορίσματα για τον κανόνα μετάβασης a, με βάση τον ορισμό του στην CafeOBJ, και δηλώνουν τυχαία αντικείμενα κατάλληλων τύπων. Επιπλέον, άλλες σταθερές μπορεί να χρειαστεί να ορισθούν μαζί με κατάλληλες εξισώσεις έτσι ώστε να γίνει ο διαχωρισμός των καταστάσεων όπως εξηγήσαμε προηγουμένως. Ακόμα κάποιες προτάσεις μπορεί να χρειασθεί να δηλωθούν ως γεγονότα (μέσω εξισώσεων). Αυτές οι προτάσεις αφορούν λήμματα στη πραγματικότητα σχετικά με τις δομές δεδομένων που χρησιμοποιούμε και όχι το ΣΠΜ (Προφανώς για να είναι ορθή η απόδειξή μας αυτά τα λήμματα πρέπει να έχουν προηγουμένως αποδειχθεί ανεξάρτητα). Τέλος, οι εξισώσεις που έχουν το s στο αριστερό τους μέρος χρησιμοποιούνται για να ορίσουμε τη διαδοχική κατάσταση της s, δηλαδή την κατάσταση μετά την εφαρμογή του κανόνα μετάβασης a. Αν ο όρος istepi(xi) αναγραφεί σε true έχουμε αποδείξει ότι ο κανόνας μετάβασης διατηρεί το κατηγόρημα predi(p, x) για την υπό-περίπτωση j. Αν, ο όρος δεν αναγραφεί σε true τότε μπορεί να πρέπει να δυναμώσουμε την επαγωγική μας υπόθεση. Εστω λοιπόν ότι SIHi είναι ο όρος της CafeOBJ που αναπαριστά τον SIH για το κατηγόρημα i. Τότε, αντί για το όρο istepi(xi) αποδεικνύουμε τον ακόλουθο: open ISTEP Declare constants denoting arbitrary objects. Declare equations denoting casei. Declare equations denoting facts if necessary. 119
eq s = a(s, y). red SIHi implies istepi(xi). close Με αυτό τον τρόπο μπορούμε να αποδείξουμε όλα τα κατηγορήματα. Στη περίπτωση που ένα κατηγόρημα αναγραφεί σε f alse τότε υπάρχουν δύο περιπτώσεις οι οποίες πρέπει να εξετάσουμε: Η υποκατάσταση που επέστρεψε f alse δεν είναι προσιτή για το σύστημά μας. Τότε πρέπει να ενδυναμώσουμε την επαγωγική μας υπόθεση με ένα λήμμα το οποίο να εκφράζει ακριβώς αυτό και έτσι ο όρος red SIHi implies istepi(xi) θα αναγραφεί επιτυχώς σε true. Η δεύτερη περίπτωση είναι η υποκατάσταση να είναι προσιτή. Τότε, αυτό σημαίνει ότι η ιδιότητα που επιθυμούμε να αποδείξουμε δεν είναι αναλλοίωτη και άρα πρέπει να επανασχεδιασθεί το σύστημά μας. 120