La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Lez. 21 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Semantica assiomatica.

Presentazioni simili


Presentazione sul tema: "Lez. 21 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Semantica assiomatica."— Transcript della presentazione:

1 Lez. 21 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Semantica assiomatica. Analisi degli algoritmi: correttezza e terminazione. Vedi: N. Wirth, Principi di programmazione strutturata, ISEDI Copyright © by Claudio Salati.

2 2 An axiomatic basis for computer programming C.A.R. Hoare Communications of the ACM, Vol. 12, No. 10, Oct Computer programming is an exact science in that all the properties of a program and all the consequences of executing it in any given environment can, in principle, be found out from the text of the program itself by means of purely deductive reasoning Vedi Ludwig Wittgenstein, Tractatus logico-philosophicus, Einaudi, punto Gia' citato.

3 3 TERMINOLOGIA Azione: evento che si compie in un intervallo di tempo finito e che produce un effetto previsto e ben definito: il significato di ogni azione deve essere ben definito Effetto: cambiamento dello stato di un oggetto (del processo) Processo sequenziale: azione complessa, scomponibile in azioni piu' semplici, eseguite una dopo l'altra in un ordine determinato Programma: descrizione di un processo tramite un linguaggio formale che permette di descrivere azioni e sequenze di azioni tramite istruzioni Oggetto: e' una entita' descritta tramite variabili. Lo stato di un oggetto e' definito dall'insieme dei valori assunti dalle variabili che lo descrivono Lo stato di un processo e' dato dall prossima istruzione da eseguire + lo stato di tutti gli oggetti del programma in quel momento Assegnamento: e' l'azione fondamentale di un processo sequenziale e consiste nell'attribuire un valore ad una variabile

4 4 TERMINOLOGIA i termini: AZIONE e PROCESSO denotano attivita`, fenomeni dinamici i termini: ISTRUZIONE e PROGRAMMA denotano descrizioni, entita` statiche un PROCESSO deriva dalla ESECUZIONE di un PROGRAMMA da parte di un processore capace di interpretarne le ISTRUZIONI (scritte in un certo linguaggio), partendo da un insieme di OGGETTI/VARIABILI dato (variabili con un valore iniziale assegnato a priori) AD UN PROGRAMMA POSSONO CORRISPONDERE PROCESSI DIVERSI IN CORRISPONDENZA A DATI DI INGRESSO DIVERSI TUTTI I PROCESSI CORRISPONDENTI AD UN PROGRAMMA SEGUONO LA STESSA REGOLA DI COMPORTAMENTO: L'ALGORITMO DESCRITTO DAL PROGRAMMA (ma la sequenza di azioni eseguita nei diversi processi puo` differire)

5 5 SEQUENZIALITA' Si suppone che la SEQUENZIALITA' in un programma sia SEMPRE BEN DEFINITA e.g. x = x + y + z significa necessariamentex = ((x + y) + z) o no? e.g. puo` significare anchex = (x + (y + z)) ? In matematica non c'e' differenza tra le due cose (associativita' dell'operatore +), ma in informatica si' (si parla di associativita' a sinistra o a destra) N.B.: l'ordine di valutazione degli operandi di un operatore in una espressione e' di norma non definito dai linguaggi di programmazione perche' un programma sia considerato corretto, questo ordine deve essere irrilevante possiamo quindi assumere un ordine di valutazione da sinistra a destra

6 6 Test di un processo sequenziale Verifico dopo ciascuna azione che lo stato del processo sia quello desiderato Verifico dopo ciascuna azione Quale e la prossima istruzione da eseguire Che il valore delle variabili del programma sia quello desiderato Il valore delle variabili del programma e quello desiderato se tra i valori delle variabili stesse sussistono certe proprieta!

7 7 TESTING VS. VERIFICA TEST (EMPIRICO) DI UN PROCESSO vs. VERIFICA FORMALE DI UN PROGRAMMA/ALGORITMO TEST EMPIRICO ESAUSTIVO DI TUTTI I PROCESSI VERIFICA FORMALE DEL PROGRAMMA (e della traduzione/interpretazione!) MA E' IMPOSSIBILE, RICHIEDE TROPPO (potenzialmente ) TEMPO! N. Wirth: "L'ESAME DI UN PROGRAMMA MEDIANTE TEST EMPIRICO PUO', AL PIU', RILEVARE LA PRESENZA DI ERRORI, MA NON PUO' GARANTIRE L'ASSENZA DI ERRORI, CIOE' LA CORRETTEZZA DEL PROGRAMMA" DA CIO' LA NECESSITA' DELLA VERIFICA FORMALE Ma questa e davvero possibile? Ci sono persino dei limiti teorici, e.g. teorema di Rice! E in pratica? Con che strumenti?

8 8 TESTING VS. VERIFICA Chi potrebbe mai pensare di effettuare il test empirico del fatto che per ogni triangolo rettangolo l'area del quadrato costruito sull'ipotenusa e' uguale alla somma delle aree dei quadrati costruiti sui cateti? Si dimostra la verita' del teorema. Si dimostra che la proprieta vale per tutti i triangoli rettangoli, e poi la si applica a ciascuno di essi. Lo stesso e' per un programma: Si dimostra la correttezza del programma, cioe' Si dimostra che e' vero che il programma trasforma un qualunque insieme I di dati in ingresso che hanno la proprieta' P (I) in un insieme di risultati O che hanno la proprieta' C (O). Quindi si applica questa proprieta a ciascun insieme I di dati di ingresso che ci interessa.

9 9 TESTING VS. VERIFICA: anticipo delle conclusioni LA VERIFICA FORMALE DI UN PROGRAMMA E' COSI' DIFFICILE (PER IL MOMENTO) CHE LA COSA MIGLIORE E' SCRIVERE (SOLO) PROGRAMMI CORRETTI E' quindi necessario/conveniente utilizzare tecniche di progettazione che garantiscano che il programma che si scrive sia corretto. Come? se esistono delle tecniche che ci consentono di ragionare su un programma gia' scritto per determinarne le proprieta (in particolare, correttezza e terminazione), potremmo adattare queste stesse tecniche e utilizzarle per scrivere dei programmi che abbiano la proprieta' di essere corretti!

10 10 VERIFICA La verifica di un programma si fa' come un caso di test, pero': si fa' a mano (per il momento, salvo sviluppi CASE) deve riguardare tutti i possibili processi derivabili dall'esecuzione del programma pertanto quando si parla delle proprieta' delle variabili (degli oggetti) in un punto del programma ci si deve riferire a proprieta' che sono valide sempre in quel punto del programma, comunque quel punto sia stato raggiunto (e, in particolare, qualunque fosse stato linsieme dei dati di ingresso per il programma). "Si annotano, prima e dopo ogni istruzione, le relazioni significative fra i valori delle variabili, valide in generale." "Valida in generale" significa: valida ogniqualvolta un (qualsiasi) processo (derivato dall'esecuzione del programma) raggiunge il punto di annotazione, indipendentemente dalle azioni eseguite precedentemente. Si verifica che ogni azione sia tale da trasformare variabili che hanno le proprieta' che valgono prima di lei, in variabili che hanno le proprieta' che si vogliono valere dopo di lei.

11 11 ASSERZIONI Asserzione: espressione delle proprieta' che hanno le variabili di un programma in un punto del suo testo. Tutte le volte che un qualunque processo di esecuzione del programma si trova a passare per quel punto (indipendentemente da come lo ha raggiunto) le variabili hanno (devono avere) le proprieta' indicate nell'asserzione. Prima e dopo una azione/istruzione definiamo due asserzioni, una premessa ( P ), e una conseguenza ( C ). L'effetto di una azione (esecuzione dell'istruzione) e' descrivibile come differenza tra la sua premessa e la sua conseguenza. Anche l'effetto di un processo sequenziale (esecuzione del programma) e' descrivibile come differenza tra la sua premessa e la sua conseguenza!

12 12 ASSERZIONI … tutte le volte che un qualunque processo di esecuzione del programma si trova a passare per quel punto... All'inizio di una funzione In tutti i punti di ritorno di una funzione (la stessa asserzione deve valere in tutti questi punti) Dopo un'istruzione if-then o if-then-else, indipendentemente dal fatto che si sia percorso un ramo o l'altro dell'istruzione if All'inizio di un ciclo, indipendentemente dal numero di iterazioni (0, 1, …, n) eseguite sul ciclo. Dopo un ciclo, indipendentemente dal numero di iterazioni (0, 1, …, n) eseguite sul ciclo.

13 13 ASSERZIONI La semantica di una azione (processo sequenziale) deve essere tale da garantire che "condizione sufficiente perche' lo stato del programma goda delle proprieta' C dopo l'esecuzione dell'azione (processo sequenziale) e' che esso goda delle proprieta' P prima dell'azione (processo sequenziale) La semantica di una istruzione/azione (processo sequenziale) e descrivibile come differenza tra la premessa P e la conseguenza C dellistruzione/azione istruzione Premessa P Conseguenza C

14 14 ALGORITMO DI EUCLIDEa // PER IL CALCOLO DEL MCD DI DUE NUMERI // NATURALI > 0 // I = {i1, i2} // P = {i k N, i k >0 : k {1, 2}} // O = {gcd}, // C = {gcd N, gcd=MCD(i1, i2)} unsigned euclide (unsigned i1, 01 unsigned i2) { 02 assert((i1>0) && (i2>0)); unsigned r, gcd; 03 unsigned k1 = i1; 04 unsigned k2 = i2; 05 assert((i1>0) && (i2>0)); assert((k1>0) && (k2>0));

15 15 ALGORITMO DI EUCLIDEb if (k2>k1) { r = k1; k1 = k2; k2 = r; } 06 assert((k1>=k2) && (k2>0)); r = k1 % k2; 07 // 0

16 16 PROGETTAZIONE Progettare un programma equivale a descrivere un insieme di azioni/istruzioni che, eseguite sequenzialmente su oggetti (dati in ingresso) per i quali vale un certo insieme di proprieta' P, portano a rendere valido un altro, desiderato, insieme di proprieta' C per i risultati in uscita. La regola di comportamento descritta dal programma deve trasformare tutti gli insiemi di dati in ingresso per i quali vale P in risultati in uscita per i quali vale C. Per progettare una azione e' necessario conoscerne la premessa (le assunzioni che e legittimo fare sui dati in ingresso) e la conseguenza desiderata. Per progettare una azione e' necessario conoscere il significato (la semantica) delle istruzioni che la descrivono.

17 17 PROGETTAZIONE Se un'azione complessa e' scomponibile (deve essere scomposta) in azioni piu' semplici, per progettare ciascuna di tali sub-azioni e' necessario conoscerne la premessa e la conseguenza: la premessa della prima sub-azione coincide con la premessa dell'azione. la conseguenza dell'ultima sub-azione coincide con la conseguenza dell'azione. N.B.: la premessa dell'ultima sub-azione coincide (circa!) con la conseguenza della prima sub-azione! I PC I1 PS I2 C

18 18 Semantica Assiomatica Tramite assiomi definisco il significato delle istruzioni fondamentali (semplici e composte) del linguaggio di programmazione Per ogni istruzione indico quale rapporto esiste tra la sua premessa e la sua conclusione Il rapporto tra premessa e conclusione e specificato in termini di relazioni che legano il testo della premessa e il testo della conclusione Dato il significato di ciascuna istruzione e possibile derivare il significato di qualunque programma scritto nel linguaggio di programmazione

19 19 SEMANTICA ASSIOMATICA: ASSEGNAMENTO Da C.A.R. Hoare, articolo citato: Consider the assignment statement: x = f; where x is an identifier for a simple variable; f is an expression of a programming language without side effects, but possibly containing x. Any assertion C( x ) which is to be true of (the value of) x after the assignment is made must also have been true of (the value of) the expression f, taken before the assignment is made, i.e. with the old value of x. Thus if C( x ) is to be true after the assignment, then C( f ) must be true before the assignment.

20 20 SEMANTICA ASSIOMATICA: ASSEGNAMENTO Da C.A.R. Hoare, articolo citato: Axiom of Assignment C 0 { x = f; } C where x is an identifier for a simple variable; f is an expression ; C 0 is obtained from C by substituting f for all occurrences of x. This pattern is described in purely syntactic terms, and it is easy to check whether any finite text conforms to the pattern.

21 21 SEMANTICA ASSIOMATICA: ASSEGNAMENTO N.B.: LAssioma dellAssegnamento non consente di derivare (immediatamente) C da C 0 ma solo C 0 da C. Cioe, ci consente solo di sapere cosa deve essere vero prima dellassegnamento (C 0 ) affinche dopo lassegnamento sia vera la conseguenza desiderata (C). Non ci consente invece di sapere direttamente che cosa sara vero dopo lassegnamento (C) sapendo quel che e effettivamente vero prima (P). Come posso fare quindi a sapere se una certa premessa P mi garantisce una certa conseguenza C? In base al fatto che sia o no vero che P C 0 : Se P C 0 allora P { x=f; } C, altrimenti no!

22 22 SEMANTICA ASSIOMATICA: esempio z = x + y; C = { z == 10 } C 0 = { (x+y) == 10 } i = i + 1; C 0 = { i < N } C = { i <= N } Infatti: C 0 = { (i+1) <= N } cioe': C 0 = { i <= N-1 } cioe': C 0 = { i < N } Perche sia vero C dopo lassegnamento deve essere vero C 0 prima dellassegnamento. C 0 non e la premessa P dellassegnamento ma deve essere implicata da P affinche lassegnamento porti alla conseguenza C desiderata.

23 23 SEMANTICA ASSIOMATICA: esempio z = x + y; P = { x <= 0; y <= 0 } C 0 = { (x+y) <= 0 } C = { z <= 0 } Perche sia vero C dopo lassegnamento deve essere vero C 0 prima dellassegnamento. La premessa P dellassegnamento implica C 0, quindi lassegnamento porta alla conseguenza C desiderata.

24 24 SEMANTICA ASSIOMATICA: regole di implicazione Da C.A.R. Hoare, articolo citato: Rules of Consequence If P { Q; } R and R S then P { Q; } S If P { Q; } R and S P then S { Q; } R i = i + 1; S = { i < 0 } P = { i <= 0 } R = { i <= 1 } Infatti: da R discende P = { i < 1 } e S P

25 25 SEMANTICA ASSIOMATICA: Composizione Da C.A.R. Hoare, articolo citato: A program generally consists of a sequence of statements which are executed one after another: { Q1; Q2; } The inference rule associated with composition states that if the proven result of the first part of a program is identical with the precondition under which the second part of the program produces its intended result, then the whole program will produce the intended result, provided that the precondition of the first part is satisfied. Rule of Composition If P { Q1; } R1 and R1 { Q2; } R then P { Q1; Q2; } R

26 26 SEMANTICA ASSIOMATICA: Composizione Se e e R1.1 R1.2 allora Q1; PR1.1 Q2; R1.2R Q1; Q2; PR Esempio: // x<=0; y<=0 (dato) z = x + y; // z<=0 z = z - 1; // z < 0 N.B.: in realta' quest'esempio illustra sia la Composizione di istruzioni che le Rules of Consequence

27 27 SEMANTICA ASSIOMATICA: Iterazione Da C.A.R. Hoare, articolo citato: The essential feature of a stored program computer is the ability to execute some portion of a program ( S ) repeatedly until a condition ( B ) goes false. while (B) S; Suppose P to be an assertion which is always true on completion of S, provided that it is also true on initiation. Then obviously P will still be true after any number of iterations of the statement S (even no iterations). Furthermore, it is known that the controlling condition B is false when the iteration finally terminates. A slightly more powerful formulation is possible in light of the fact that B may be assumed to be true on initiation of S.

28 28 SEMANTICA ASSIOMATICA: Iterazione Da C.A.R. Hoare, articolo citato: Rule of Iteration If P B { S; } P then P { while (B) S; } B P P e' chiamato invariante del ciclo perche' deve essere vero ad ogni iterazione. Quello che fa un ciclo e' rendere falsa B pur continuando a mantenere vera P. P deve essere vera fino da prima dell'inizio del ciclo! E' B che non necessariamente e' falsa fin dall'inizio!

29 29 SEMANTICA ASSIOMATICA: Iterazione // P while ( B ) { // P B S; // P } // P B N.B.: assumendo P B { S; } P B S P P P P B FALSE TRUE

30 30 Iterazione: esempio int findMinEl(unsigned int N, double v[]) { 1 // P = { N 1, double v[N] } int i = 0; int iMin = 0; 2 // P1 = {..., 0 iMin i, 0 i N-1, j=0..i: v[j] v[iMin] } while ( i < N-1 ) { 3 i += 1; 4 if ( v[i] < v[iMin] ) iMin = i; 5 } 6 // C = {..., 0 iMin N-1, j=0..N-1: v[j] v[iMin] } return iMin; 7 } 8 Alla fine del ciclo iMin e lindice dellelemento minimo del vettore v. Ma anche allinizio del ciclo iMin e lindice dellelemento minimo di quella parte del vettore v che ho gia esaminato! Quello che cambia tra linizio e la fine e il valore di verita della condizione di controllo del ciclo: nel vettore v ci sono ancora elementi non esaminati?

31 31 SEMANTICA ASSIOMATICA: Invarianti In realta' ogni asserzione e' un invariante. Sono in particolare invarianti la premessa e la conseguenza di una funzione: un chiamante deve garantire che la premessa della funzione chiamata sia vera al momento della chiamata; il chiamato garantisce quindi la veridicita' della propria conseguenza al momento del ritorno (di qualunque statement return ). E' questo il contratto che lega una funzione e i suoi clienti! contratto chiamante/chiamato aspetti sintattici: prototipo della funzione aspetti semantici: prototipo della funzione + (premessa e conseguenza)

32 32 SEMANTICA ASSIOMATICA: Invarianti N. Wirth, Principi di programmazione strutturata, ISEDI : L'indicazione degli invarianti ciclici rilevanti di ogni loop e' la base di ogni buona documentazione. C. Salati, Algoritmi Avanzati, Lez. 2, pag. 32: L'indicazione della premessa e della conseguenza di ogni funzione (cioe' del suo del contratto chiamante-chiamato) e' parte essenziale di ogni buona documentazione. Corollario: poiche' un programma non e' nient'altro che la sua funzione main(), quanto detto prima si applica in particolare anche ad un programma nel suo complesso.

33 33 SEMANTICA ASSIOMATICA: cicli COSTRUZIONE/VERIFICA di un ciclo WHILE : 1.SI SCEGLIE UN PUNTO DI TAGLIO z 2.SI FISSA LA PREMESSA P CHE DEVE VALERE NEL PUNTO DI TAGLIO z+ 3. APPLICANDO LE REGOLE PRECEDENTI E SEGUENDO IL CICLO SI DERIVA LA CONSEGUENZA C CHE DEVE VALERE NEL PUNTO DI TAGLIO z- 4. PERCHE' LA RICHIUSURA DEL CICLO SIA LEGALE DEVE RISULTARE C P IL PUNTO DI TAGLIO E' SCELTO CONVENIENTEMENTE A MONTE DEL TEST B, COSI' CHE –P e` la premessa del WHILE nel suo complesso –P B e` la conseguenza del WHILE nel suo complesso l'idea e` che all'inizio P sia vera in forma banale e che ogni iterazione ne aumenti la significativita` garantire la terminazione significa arrivare a falsificare B

34 34 Confluenze e Ramificazioni In un ciclo while sono presenti: un punto di ramificazione del programma; un punto di confluenza di due rami del programma. Basandosi sulle regole di implicazione si e' assunto che: quando piu' cammini del programma si congiungono nel punto che precede una istruzione R, la premessa P(R) deve essere logicamente implicata da ciascuna delle conseguenze C(S1), …, C(Sn) di tutte le istruzioni S1, …, Sn che confluiscono in R. un punto di ramificazione di un programma e' sempre associato ad una espressione booleana B. Se vale la premessa P(B), allora sul ramo associato al valore vero di B vale la conseguenza B P sul ramo associato al valore falso di B vale la conseguenza B P

35 35 SEMANTICA ASSIOMATICA: Istruzioni condizionali Le regole di confluenza e ramificazione ci consentono di trattare anche gli statement if-then e if-then-else Da N. Wirth, Principi di programmazione strutturata, ISEDI Rule of statement if-then If P B { S; } C and P B C then P { if (B) S; } C Rule of statement if-then-else If P B { S1; } C and P B { S2; } C then P { if (B) S1; else S2; } C

36 36 SEMANTICA ASSIOMATICA: Istruzioni condizionali // P if ( B ) { // P B S; // C } // C N.B.: assumendo P B { S; } C and P B C B S P C P B FALSE TRUE C

37 37 SEMANTICA ASSIOMATICA: Istruzioni condizionali // P if( B ) { // P B S1; // C } else { // P B S2; // C } // C N.B.: assumendo P B { S1; } C and P B { S2; } C B S2 P CC P B FALSETRUE S1 C

38 38 SEMANTICA ASSIOMATICA: Istruzioni condizionali Esempio: // 0 <= x; 0 <= y if (x >= y) { // 0 = y x = y; // 0 <= x; 0 <= y; x == y } // else 0 <= x; 0 <= y; x < y // 0 <= x <= y; 0 <= y

39 39 SEMANTICA ASSIOMATICA: Istruzioni condizionali Esempio: // P = { N 1, int v[N], 0 iMin

40 40 TEOREMA DI BOEHM-JACOPINI QUALSIASI PROGRAMMA DESCRITTO TRAMITE FLOW- CHART PUO' ESSERE TRASFORMATO IN UN ALTRO PROGRAMMA NEL QUALE LA FLOW-CHART CONTIENE SOLO LE SEGUENTI FORME DI COMPOSIZIONE: SEQUENZA, SELEZIONE, ITERAZIONE AGGIUNGENDO SOLO STATEMENT DI ASSEGNAMENTO, VARIABILI AUSILIARIE, E TEST SU TALI VARIABILI SONO STATI DATI MOLTI ALGORITMI DI TRASFORMAZIONE SEMPRE PIU' "STRINGENTI", CIOE' TALI DA MANTENERE IL FLUSSO DI CONTROLLO "LOGICO" DELLA FLOW-CHART ORIGINALE

41 41 TEOREMA DI BOEHM-JACOPINI: esercizio esercizio: SCHEMATIZZARE UN ALGORITMO (banale) BASATO SU UNA SOLA VARIABILE AUSILIARIA CHE TRASFORMI QUALUNQUE FLOW-CHART IN UNA FLOW-CHART BASATA SOLO SULLE REGOLE DI COMPOSIZIONE SEQUENZA, SELEZIONE, ITERAZIONE (si pensi a come funziona un calcolatore, a numerare i box della flow-chart,...)

42 42 TEOREMA DI BOEHM-JACOPINI: conseguenza Poiche' abbiamo definito la semantica cioe' la regola di trasformazione premessa / conseguenza di tutte le forme di composizione di statement necessarie per esprimere qualunque algoritmo secondo il teorema di Boehm- Jacopini, abbiamo in linea di principio tutti gli strumenti necessari ad analizzare e verificare la correttezza di qualunque algoritmo/programma Abbiamo anche gli strumenti necessari a progettare (esprimere) correttamente qualunque algoritmo/programma!

43 43 ESEMPIO DI VERIFICA DI CORRETTEZZA int moltiplica (int x, int y) { int z = 0; int u = x; while (u>0) { z = z + y; u = u - 1; } return (z); } Cosa significa dire che moltiplica() e' corretta? Bisogna per prima cosa indicarne premessa e conseguenza!

44 44 ESEMPIO DI VERIFICA DI CORRETTEZZA int moltiplica (int x, int y) { assert (x>=0 && y>=0);// P int z = 0; int u = x; while (u>0) { z = z + y; u = u - 1; } assert((x>=0 && y>=0) && z==x*y); // C return (z); } moltiplica() e' corretta se condizione sufficiente perche' z abbia la proprieta' indicata nell' assert() finale e' che x e y abbiano la proprieta' indicata nell' assert() iniziale.

45 45 ESEMPIO DI VERIFICA DI CORRETTEZZA int moltiplica (int x, int y) { assert (x>=0 && y>=0 && x*y==x*y);// P int z = 0; int u = x; assert((x>=0 && y>=0) && (u>=0 && z+u*y==x*y)); // A1 while (u>0) { assert((x>=0 && y>=0) && (u>0 && z+u*y==x*y)); // A2 z = z + y; u = u - 1; assert((x>=0 && y>=0) && (u>=0 && z+u*y==x*y)); // A3 } // assert((x>=0 && y>=0) && // (u==0 && z+u*y==x*y)); // A4 assert((x>=0 && y>=0) && z==x*y); // C return (z); }

46 46 ESEMPIO DI VERIFICA DI CORRETTEZZA - nota 0 Nota che: A2 e derivata da A1 per il fatto che lunica cosa che le separa e il test (u>0) Se A1 e verificata, allora e verificata anche A2 A4 deriva da A1 per lAssioma dellIterazione (a patto che il ciclo sia ben strutturato) Se A1 e verificata (e il ciclo e ben strutturato), allora e verificata anche A4 P e (deve essere) garantita dal chiamante, secondo quanto previsto dal contratto chiamante-chiamato

47 47 ESEMPIO DI VERIFICA DI CORRETTEZZA - nota 1 assert((x>=0 && y>=0) && (u>0 && z+u*y==x*y));// A2 z = z + y; u = u - 1; assert((x>=0 && y>=0) && (u>=0 && z+u*y==x*y)); // A3 Infatti: A3 = {x>=0, y>=0, (u>=0, z+u*y==x*y)} sostituendo nel testo di A3 (u-1) a u e (z+y) a z si ottiene: A3 0 = {x>=0, y>=0, ((u-1)>=0, (z+y)+(u-1)*y==x*y)} cioe': A3 0 = {x>=0, y>=0, (u>=1, z+y+u*y-y==x*y)} cioe': A3 0 = {x>=0, y>=0, (u>0, z+u*y==x*y)} = A2 (quindi A2 A3 0 ) Il corpo del ciclo mantiene linvariante, cioe il ciclo e ben strutturato

48 48 ESEMPIO DI VERIFICA DI CORRETTEZZA - nota 2 assert (x>=0 && y>=0 && x*y==x*y); // P int z = 0; int u = x; assert((x>=0 && y>=0) && (u>=0 && z+u*y==x*y)); // A1 Infatti: A1 = {(x>=0, y>=0), (u>=0, z+u*y==x*y)} sostituendo nel testo di A1 x a u e 0 a z si ottiene: A1 0 = {x>=0, y>=0, (x>=0, 0+x*y==x*y)} cioe': A1 0 = {x>=0, y>=0, x*y==x*y} = P (quindi P A1 0 ) Linizializzazione del ciclo e corretta, in quanto ne rende vero linvariante

49 49 ESEMPIO DI VERIFICA DI CORRETTEZZA - nota 3 assert((x>=0 && y>=0) && (u>=0 && z+u*y==x*y));// A1 while (u>0) {...} // assert((x>=0 && y>=0) && // (u==0 && z+u*y==x*y));// A4 assert((x>=0 && y>=0) && z==x*y);// C Infatti: Applicando la regola dell'iterazione (la cosa e' legittima per quanto dimostrato in "nota 1"), dalla premessa A1 del ciclo, essendo per la condizione di controllo: B = {u>0}, si ha: A4 = A1 B = {x>=0, y>=0, (u>=0, z+u*y==x*y), u<=0} cioe': A4 = {x>=0, y>=0, u==0, z+0*y==x*y} cioe': A4 = {x>=0, y>=0, u==0, z==x*y} = C Il ciclo fa quello che vogliamo che faccia

50 50 CORRETTEZZA E TERMINAZIONE Una dimostrazione di correttezza non dimostra che il programma termina. Dice solo che, se termina, fornisce il risultato desiderato. Se terminasse, nonMoltiplica() calcolerebbe x*y, ma per x>0 non termina! int nonMoltiplica (int x, int y) { assert (x>=0 && y>=0); int z = 0; int u = x; assert((x>=0 && y>=0) && (u>=0 && z+u*y==x*y)); while (u>0) { assert(x>=0 && y>=0 && u>0 && z+u*y==x*y); // z = z + y; u = u - 1; assert(x>=0 && y>=0 && u>=0 && z+u*y==x*y); } assert((x>=0 && y>=0) && z==x*y); return (z); }

51 51 DIMOSTRAZIONE DI TERMINAZIONE Come possiamo essere sicuri che moltiplica() termini? Perche' ad ogni iterazione u (che e' per ipotesi 0, e che se il corpo del ciclo viene eseguito deve essere strettamente positiva) viene decrementata di 1 ( u e' monotona descescente con le iterazioni del ciclo). Quando u raggiunge il valore 0, come deve necessariamente succedere, il ciclo termina. N.B.: la condizione dello statement while avrebbe potuto essere scritta anche come (u!=0) LA TERMINAZIONE DI UN PROGRAMMA E' GARANTITA DALLA TERMINAZIONE DI TUTTI I SUOI CICLI (E DELLE SUE RICORSIONI!) Per garantire la terminazione di ciascun ciclo si generalizza l'argomentazione utilizzata per dimostrare la terminazione del ciclo della funzione moltiplica()

52 52 TERMINAZIONE DI UN CICLO (o di una ricorsione) Consideriamo il ciclo while ( B ) S; Si definisce una grandezza intera N funzione dello stato degli oggetti del programma. N e' (deve essere) tale che se B e' vera allora vale N 0. Nel processo di esecuzione del ciclo N e' (deve essere) monotona decrescente: Dopo ogni iterazione N e' (strettamente) minore di quanto era prima. Cioe', l'esecuzione dell'istruzione S provoca una diminuzione del valore di N. Quindi ad un certo punto diventera' N < 0: quando cio' succede B deve necessariamente essere falsa. Nel caso particolare di moltiplica() e': N = u-1

53 53 ANALISI DI UN CICLO Cosa devo verificare di un ciclo? while ( B ) S; 1.Che sia inizializzato bene, cioe' che le istruzioni precedenti siano tali da rendere vero l'invariante quando si raggiunge il ciclo. 2.Che il ciclo sia ben strutturato, cioe' che mantenga vero l'invariante ad ogni iterazione. 3.Che il ciclo faccia quello che si desidera, cioe' che la combinazione dell'invariante & della negazione della condizione di controllo implichi la conseguenza desiderata del ciclo. Cosa devo dimostrare ancora di un ciclo? 4.Che termini.

54 54 Esempio: Fattoriale.1 // I = { n } // P = { n I, n>=0 } // O = { fatt }, // C = { fatt N, fatt=n!} unsigned fattoriale (unsigned n) { // P = { n >= 0 } unsigned fatt = 1; unsigned t = 0; while (t

55 55 Esempio: Fattoriale.2 Dove devo inserire delle asserzioni? unsigned fattoriale (unsigned n) { // P = { n >= 0 } unsigned fatt = 1; unsigned t = 0; // I = { invariante del ciclo } while (t=n } // C = { fatt = n! } return(fatt); }

56 56 Esempio: Fattoriale.3 Ricetta: Invento un invariante tentativo che descriva la logica del problema (l'asserzione I). Verifico se l'asserzione I e' plausibile: 1.e' resa vera dall'inizializzazione del ciclo? Verifico se l'asserzione I e' tale da soddisfare la conseguenza desiderata del ciclo: 2.I & la negazione della condizione di controllo (cio' che ho garantito all'uscita dal ciclo) implicano C (cio' che desidero all'uscita dal ciclo)? Verifico se il ciclo e' ben strutturato: 3.il corpo del ciclo e' tale da mantenere vero l'invariante del ciclo? Verifico che il ciclo termini necessariamente: 4.il corpo del ciclo e' tale da portare a falsificare la condizione di controllo del ciclo?

57 57 Esempio: Fattoriale.4 // I = { n } // P = { n I, n>=0 } // O = { fatt }, // C = { fatt N, fatt=n!} unsigned fattoriale (unsigned n) { // P { n >= 0 } unsigned fatt = 1; unsigned t = 0; // I = { t <= n; fatt = t! } // N = n-t-1 while (t=n) } C = { fatt = n! } return(fatt); }


Scaricare ppt "Lez. 21 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Semantica assiomatica."

Presentazioni simili


Annunci Google