Verifica dei programmi

Documenti analoghi
Semantica Assiomatica

Due algoritmi di ordinamento. basati sulla tecnica Divide et Impera: Mergesort e Quicksort

Sistemi Web per il turismo - lezione 3 -

Informatica B. Sezione D. Scuola di Ingegneria Industriale Laurea in Ingegneria Energetica Laurea in Ingegneria Meccanica

Capitolo 5: Macchine di Turing e calcolabilitá secondo Turing

PIANO DI LAVORO. a.s / 2016

Gestione di files Motivazioni

Correttezza. Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1. Dispensa 10. A. Miola Novembre 2007

Testing: basato su analisi dinamica del codice. Metodi Formali: basato su analisi statica del codice.

Metodi e Modelli per l Ottimizzazione Combinatoria Il problema del flusso di costo minimo

AA LA RICORSIONE

Informatica Teorica. Macchine a registri

Testi di Esercizi e Quesiti 1

CAPITOLO V. DATABASE: Il modello relazionale

Gli algoritmi: definizioni e proprietà

Sistemi Operativi Anno Accademico 2011/2012. Segnali: Interrupt software per la gestione di eventi asincroni

Algoritmi di Ricerca. Esempi di programmi Java

Programmazione Orientata agli Oggetti in Linguaggio Java

Introduzione alle macchine a stati (non definitivo)

(1) (2) (3) (4) 11 nessuno/a (1) (2) (3) (4) X è il minore tra A e B nessuno/a X è sempre uguale ad A X è il maggiore tra A e B

Ricerca Operativa e Logistica

INDICAZIONI PER LA RICERCA DEGLI ASINTOTI VERTICALI

Semantica dei programmi. La semantica dei programmi è la caratterizzazione matematica dei possibili comportamenti di un programma.

Programmazione Dichiarativa. Programmazione Logica. SICStus PROLOG PROLOG. Bob Kowalski: "Algoritmo = Logica + Controllo"

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

STRUTTURE NON LINEARI

Capitolo 7: Teoria generale della calcolabilitá

Creare una funzione float square(float x). La funzione deve restituire il quadrato del parametro x.

Algoritmi e Strutture Dati & Laboratorio di Algoritmi e Programmazione

VBA è un linguaggio di scripting derivato da Visual Basic, da cui prende il nome. Come ogni linguaggio ha le sue regole.

Geometria Superiore Esercizi 1 (da consegnare entro... )

Interpretazione astratta

La macchina universale

Unità Didattica 3 Linguaggio C. Generalità sulle Funzioni. Variabili locali e globali. Passaggio di parametri per valore.

DI D AGRA R MM M I M A BLOCC C H C I TEORI R A E D D E SERC R I C ZI 1 1

Appunti del corso di Informatica 1 (IN110 Fondamenti) 3 Modelli di calcolo

Linguaggi. Claudio Sacerdoti Coen 11/04/ : Semantica della logica del prim ordine. Universitá di Bologna

Descrizione di un algoritmo

Il comando provoca il salvataggio dello stato e la terminazione dell esecuzione.

PARTE III MACCHINE A REGISTRI

Note su quicksort per ASD (DRAFT)

Calcolare il massimo di una lista

Il linguaggio di specifica formale Z

Il calcolatore. Architettura di un calcolatore (Hardware)

Lezione 8. La macchina universale

Laboratorio di Algoritmi e Strutture Dati II Semestre 2005/2006. Ordinamenti: mergesort e quicksort

Progetto Lauree Scientifiche Liceo Classico L.Ariosto, Ferrara Dipartimento di Matematica Università di Ferrara 24 Gennaio 2012

Esonero del corso di Programmazione a Oggetti

Ottimizzazione nella gestione dei progetti Capitolo 4: la gestione dei costi (Programmazione multimodale): formulazioni

F (x) = f(x) per ogni x I. Per esempio:

La selezione binaria

PROVA FINALE V. AULETTA G. PERSIANO ALGORITMI II - -MAGIS INFO

Sviluppare Programmi Corretti

Elementi di semantica operazionale

Verifica che una grammatica sia Context Free nel GrammaReader

UD4 - MATLAB. M-file. Efficienza degli algoritmi. Formati d uscita

TEORIA RELAZIONALE: INTRODUZIONE

INFORMATICA 1 L. Mezzalira

Rappresentazione della conoscenza. Lezione 11. Rappresentazione della Conoscenza Daniele Nardi, 2008Lezione 11 0

Tipologie di macchine di Turing

Trasformazioni del codice sorgente. Programmazione di qualità per sistemi embedded

Corso di Programmazione Algoritmi Fondamentali. Minimo fra 3 valori. Minimo fra 3 valori Algoritmo. Dott. Pasquale Lops

Laboratorio di Programmazione Lezione 1. Cristian Del Fabbro

Verifica parte IIA. Test (o analisi dinamica) Mancanza di continuità. Esempio

DAL DIAGRAMMA AL CODICE

Esercizi per il corso di Algoritmi e Strutture Dati

IL CONCETTO DI FILE. È illecito operare oltre la fine del file.

Dall italiano al linguaggio della logica proposizionale

Una funzione è detta ricorsiva se chiama, direttamente o indirettamente, se stessa. In C tutte le funzioni possono essere usate ricorsivamente.

Linguaggio del calcolatore. Algebra di Boole AND, OR, NOT. Notazione. And e or. Circuiti e reti combinatorie. Appendice A + dispense

PROBLEMA DELLA RICERCA DI UN ELEMENTO IN UN ARRAY E ALGORITMI RISOLUTIVI

Arduino: Programmazione

Bontà dei dati in ingresso

Prof. Giuseppe Chiumeo. Avete già studiato che qualsiasi algoritmo appropriato può essere scritto utilizzando soltanto tre strutture di base:

Laboratorio 07. Programmazione - CdS Matematica. Michele Donini 10 dicembre 2015

Matlab: Strutture di Controllo. Informatica B

Corso di Calcolo Numerico

PROGRAMMA DI SCIENZE E TECNOLOGIE APPLICATE 2015/2016 Classe 2ª Sez. C Tecnologico

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI

Esercitazione Dicembre 2010 (2 ore)

Informatica 3. Informatica 3. LEZIONE 10: Introduzione agli algoritmi e alle strutture dati. Lezione 10 - Modulo 1. Importanza delle strutture dati

Teoria degli insiemi

Lezione 6 Le pile. Informatica. 28 Aprile 2016

Fondamenti dei linguaggi di programmazione

Elementi di semantica denotazionale ed operazionale

La programmazione con vincoli in breve. La programmazione con vincoli in breve

COMPILAZIONE. Tarsformazione di linguaggi

COGNOME E NOME (IN STAMPATELLO) MATRICOLA

Lo sviluppo del software: usi e clausole commentate Aspetti Tecnici. Prof. Franco Sirovich Dipartimento di Informatica Università di Torino

ITCS Erasmo da Rotterdam. Anno Scolastico 2014/2015. CLASSE 4^ M Costruzioni, ambiente e territorio

FONDAMENTI di INFORMATICA L. Mezzalira

RICORSIONE - schema ricorsivo (o induttivo) si esegue l'azione S, su un insieme di dati D, mediante eventuale esecuzione di

I metodi formali nel processo di sviluppo del software

4.1 Modelli di calcolo analisi asintotica e ricorrenze

INTRODUZIONE ALLE BASI DATI RELAZIONALI

SISTEMI DI NUMERAZIONE DECIMALE E BINARIO

Il Metodo Scientifico

Esercizi Capitolo 5 - Alberi

I file Laboratorio di Linguaggi di Programmazione a.a. 2001/2002

Elementi di Informatica

Transcript:

Verifica dei programmi Consiste nella specifica e nella dimostrazione delle proprietà dei programmi. Per specificare le proprietà utilizzeremo la logica del I ordine. Per dimostrare che le proprietà specificate sono soddisfatte dal programma in questione introdurremo le principali tecniche di verifica. Una specifica è una descrizione precisa di proprietà che un programma dovrebbe avere. Faremo vedere come inserire tali specifiche nel programma (annotazioni di programma). 1

Verifica dei programmi Concentreremo la nostra attenzione su: Proprietà di correttezza parziale (o di safety), che asseriscono che certi stati, tipicamente stati di errore, non possono mai occorrere durante l esecuzione del programma. Il metodo di dimostrazione usato è quello delle asserzioni induttive. Proprietà di correttezza totale (di progresso), che asseriscono che durante l esecuzione del programma certi stati vengono raggiunti. In generale una dimostrazione di correttezza totale viene così suddivisa: Dimostrazione di correttezza parziale Terminazione (metodo di dimostrazione: funzione di ranking) 2

Metodo fondazionale delle asserzioni induttive È un metodo basato sull induzione matematica. Per dimostrare che ogni stato della computazione soddisfa una certa formula ϕ della logica del I ordine: si dimostra come caso base che ϕ vale all inizio dell esecuzione, si assume per ipotesi induttiva che ϕ vale correntemente e si dimostra come passo induttivo che ϕ vale dopo un altro passo del programma. L applicazione del metodo può essere semplice. Tuttavia è possibile incontrare qualche difficoltà nella scoperta di annotazioni aggiuntive necessarie per l induzione. 3

Metodo fondazionale della funzione di ranking Consiste nell associare ad ogni loop e funzione ricorsiva una funzione (funzione di ranking) che mappa le variabili del programma in un dominio ben fondato, Quindi si dimostra che, durante la computazione del programma, il valore della funzione di ranking si riduce. Poichè la relazione è ben fondata, i loop e le ricorsioni devono fermarsi. 4

Linear search @pre @post bool LinearSearch(int [] a, int l, int u, int e) { for @ (int i := l;i u;i := i+1){ if (a[i] = e) return true; } return false; } LinearSearch ricerca il valore e all interno del range [l, u] di un array a. Restituisce true sse l array dato contiene il valore e fra il lower bound l e l upper bound u. Si comporta correttamente solo se 0 l ed u < a. 5

Binary search @pre @post bool BinarySearch(int [] a, int l, int u, int e) { if (l > u) return false; else { int m := (l+u) div 2; if (a[m] = e) return true; else if (a[m] < e) return BinarySearch(a, m+1, u, e); else return BinarySearch(a, l, m 1, e); } } BinarySearch è una funzione ricorsiva che ricerca il valore e nel range [l,u] di un array ordinato a di interi. Restituisce true sse a 6

contiene il valore e nel range [l, u]. Funziona correttamente solo se 0 l e u a. Un livello di ricorsione opera come segue: Se l > u allora il sottoarray (vuoto) non può contenere e e si restituisce false; Altrimenti si esamina l elemento di mezzo a[m] (a div b = Def a b ); Se a[m] = e allora si restituisce true; Altrimenti si effettua la ricorsione sulla metà destra se a[m] < e, sulla metà sinistra se a[m] > e. 7

Annotazioni di programma Un annotazione è una formula della logica del I ordine le cui variabili libere includono soltanto dele variabili del programma. Un annotazione F posta accanto ad un istruzione asserisce che F è vera tutte le volte che il controllo del programma raggiunge quella istruzione. La specifica di funzione è una coppia di annotazioni: Precondizione di funzione: formula F le cui variabili libere includono solo i parametri formali. Specifica sotto quali input deve essere eseguita la funzione. Postcondizione di funzione: è una formula G le cui variabili libere includono solo i parametri formali e la variabile speciale rv che rappresenta il valore di output della funzione. 8

Linear search con specifica di funzione @pre 0 l u < a @post rv ( i.l i u a[i] = e) bool LinearSearch(int [] a, int l, int u, int e) { for @ (int i := l;i u;i := i+1){ if (a[i] = e) return true; } return false; } La precondizione asserisce che il lower bound l deve essere non più piccolo di 0 e che l upper bound u deve essere più piccolo della lunghezza dell array. La post condizione asserisce che il valore di ritorno rv è true sse a[i] = e per qualche indice i [l,u] di a. 9

Linear search con specifica di funzione 2. @pre @post rv ( i.0 l i u < a a[i] = e) bool LinearSearch(int [] a, int l, int u, int e) { if (l < 0 u a ) return false; for @ (int i := l;i u;i := i+1){ if (a[i] = e) return true; } return false; } 10

Binary search con specifica di funzione @pre 0 l u < a sorted(a,l,u) @post rv ( i.l i u a[i] = e) bool BinarySearch(int [] a, int l, int u, int e) { if (l > u) return false; else { int m := (l+u) div 2; if (a[m] = e) return true; else if (a[m] < e) return BinarySearch(a, m+1, u, e); else return BinarySearch(a, l, m 1, e); } } La postcondizione è identica a quella di LinearSearch ma la precondizione dichiede anche che l array sia ordinato. 11

Loop invariant Ad ogni ciclo for e while viene associata un annotazione detta loop invariant. Un ciclo while while } @F ( condition ) { body Dice: eseguire body finché vale condition. L asserzione F deve valere all inizio di ogni iterazione. Viene valutata prima di condition e quindi deve valere anche sull iterazione finale, quando condition è false. 12

Loop invariant for } @F ( initialize ; condition ; increment ) { body può essere tradotto nel ciclo equivalente initialize ; while @F ( condition ) { body increment 13

} F deve valere dopo che initialize è stato valutato e, su ogni iterazione, prima che condition venga valutata. 14

Linear search con loop invariant @pre 0 l u < a @post rv ( i.l i u a[i] = e) bool LinearSearch(int [] a, int l, int u, int e) { for @L : l i ( j.l j < i a[j] e) (int i := l;i u;i := i+1){ if (a[i] = e) return true; } return false; } 15

Asserzioni Le annotazioni possono essere aggiunte in qualunque parte del programma. Quando un annotazione non è una precondizione di funzione, una postcondizione, o un loop invariant, la chiamiamo asserzione. Le asserzioni permettono ai programmatori di fornire un commento formale. Ad esempio, se all istruzione i := i+k; il programmatore pensa che k debba essere positivo, si può aggiungere un asserzione che afferma la supposizione: @ k > 0; i := i+k; 16

Correttezza parziale Useremo il metodo delle asserzioni induttive per dimostrare che un programma è parzialmente corretto. Il metodo riduce ogni funzione e le sue annotazioni ad un insieme finito di condizioni di verifica (VC) che sono formule della logica del I ordine. Se tutte le VC di una funzione sono valide, la funzione soddisfa la sua specifica. La riduzione avviene in due passi: prima, ogni funzione del programma annotato viene suddivisa in un insieme finito di cammini di base; poi ogni cammino di base genera una condizione di verifica (VC). 17

I loop e le funzioni ricorsive complicano le dimostrazioni di correttezza parziale perché creano un numero non limitato di cammini (da quando si entra in una funzione a quando si esce). Un cammino è una sequenza di istruzioni di programma. Per quanto riguarda i loop, gli invarianti di loop tagliano il cammino in un numero finito di cammini di base. Per le funzioni ricorsive invece, è la specifica di funzione a tagliare il cammino. Un cammino di base (semplice, elementare) è una sequenza di istruzioni che comincia dalla precondizione di funzione, o da un loop invariant e finisce in un loop invariant, in un asserzione, o nella postcondizione della funzione. Inoltre, un loop invariant può occorrere solo all inizio o alla fine di un cammino di base. Quindi, i cammini base non attraversano i loop. 18

Cammino 1: Cammini di base di LinearSearch annotato @pre 0 l u < a i := l; @L : l i ( j.l j < i a[j] e) Cammino 2: @L : l i ( j.l j < i a[j] e) assume i u; assume a[i] = e; rv := true; @post rv ( i.l i u a[i] = e) 19

Cammino 3: Cammini di base di LinearSearch annotato @L : l i ( j.l j < i a[j] e) assume i u; assume a[i] e; i := i+1; @L : l i ( j.l j < i a[j] e) Cammino 4: @L : l i ( j.l j < i a[j] e) assume i > u; rv := false; @post rv ( i.l i u a[i] = e) 20

Chiamate di funzione Come i cicli, anche le chiamate di funzione ricorsive creano un numero non limitato di cammini. Come gli invarianti di loop tagliano (cut) i cicli per produrre un numero finito di cammini base, le specifiche di funzione tagliano le chiamate di funzione. 21

Binary search con asserzioni di chiamata di funzione @pre 0 l u < a sorted(a,l,u) @post rv ( i.l i u a[i] = e) bool BinarySearch(int [] a, int l, int u, int e) { if (l > u) return false; else { int m := (l+u) div 2; if (a[m] = e) return true; else if (a[m] < e) { @ R 1 : 0 m+1 u < a sorted(a,m+1,u); return BinarySearch(a, m+1, u, e); } else { @ R 2 : 0 l m 1 < a sorted(a,l,m 1); return BinarySearch(a, l, m 1, e); } } } 22

Cammino 1: Cammini di base @pre 0 l u < a sorted(a,l,u) assume l > u; rv := false; @post rv ( i.l i u a[i] = e); Cammino 2: @pre 0 l u < a sorted(a,l,u) assume l u; m := (l+u) div 2; assume a[m] = e; rv := true; @post rv ( i.l i u a[i] = e); 23

Cammino 3: Cammini di base @pre 0 l u < a sorted(a,l,u) assume l u; m := (l+u) div 2; assume a[m] e; assume a[m] < e; @R 1 : 0 m+1 u < a sorted(a,m+1,u); 24

Cammino 5: Cammini di base @pre 0 l u < a sorted(a,l,u) assume l u; m := (l+u) div 2; assume a[m] e; assume a[m] e; @ R 2 : 0 l m 1 < a sorted(a,l,m 1); 25

Cammino 4: Cammini di base @pre 0 l u < a sorted(a,l,u) assume l u; m := (l+u) div 2; assume a[m] e; assume a[m] < e; assume v 1 i.m+1 i u a[i] = e; rv := v 1 ; @post rv ( i.l i u a[i] = e); 26

Cammino 6: Cammini di base @pre 0 l u < a sorted(a,l,u) assume l u; m := (l+u) div 2; assume a[m] e; assume a[m] e; assume v 2 i.l i m 1 a[i] = e; rv := v 2 ; @post rv ( i.l i u a[i] = e); 27

Le linee: Spiegazioni assume v 1 i.m+1 i u a[i] = e; rv := v 1 ; sono ottenute come segue: Si traduca lo statement: return BinarySearch(a, m+1, u, e); in un assegnamento a rv: rv := BinarySearch(a, m+1, u, e); Poi, poichè la precondizione vale (dal cammino 3), supponiamo che valga anche la postcondizione. Quindi descriviamo la chiamata di funzione con una relazione basata sulla postcondizione: 28

G[a,l,u,e,rv] : rv i.l i u a[i] = e. In questo caso specifico la relazione è G[a,m+1,u,e,v 1 ], dove v 1 è una variabile nuova che cattura il valore restituito. Nel cammino base si assuma tale relazione e si usi il valore di ritorno v 1 nell assegnamento: assume G[a,m+1,u,e,v 1 ]; rv := v 1 ; 29

Stati del programma Uno stato del programma è un assegnamento di valori alle variabili del programma. Le variabili del programma includono una variabile distinta pc, il contatore di programma. Esempio: s : {pc L 1,a [2,5,3,0],l 0,u 3,i 0} è uno stato di Linear Search. 30

Condizioni di verifica Il nostro obiettivo è quello di ridurre una funzione annotata ad un insieme finito di formule della logica del I ordine chiamate condizioni di verifica. Se condizioni di verifica sono tutte valide, il comportamento della funzione concorde con le sue annotazioni. I cammini di base vengono ridotti a condizioni di verifica utilizzando un meccanismo, detto weakest precondition, che incorpora gli effetti prodotti dalle istruzioni del programma in formule della logica del I ordine. 31

Condizioni di verifica La weakest precondition wp(f, S) è una funzione che mappa una formula del I ordine e un istruzione di un programma in una formula del I ordine, gode della proprietà che se dato uno stato s, si ha che s = wp(f,s), e se l istruzione S viene eseguita su s producendo lo stato s, allora s = F. La wp(f,s) è definita per i due tipi di istruzione presenti nei cammini di base (assunzione e assegnamento) come segue: Assunzione: cosa deve valere prima che l istruzione assume c venga eseguita per assicurare che F valga dopo? Se c F 32

vale prima, allora soddisfacendo c in assume c si garantisce che F valga dopo. wp(f,assume c) c F. Assegnamento: cosa deve valere prima che l istruzione v := e venga eseguita per assicurare che F[v] valga dopo? Se F[e] vale prima, allora assegnando e a v con v := e si garantisce che F[v] valga dopo.: wp(f[v],v := e) F[e]. Per una sequenza di istruzioni S 1 ;...;S n, definiamo: wp(f,s 1 ;...;S n ) wp(wp(f,s n ),S 1 ;...;S n 1 ) Quindi: perchè F possa valere dopo aver eseguito una sequenza di istruzioni S 1 ;...;S n, wp(f,s 1 ;...;S n ) deve valere prima di 33

eseguire le istruzioni. La condizione di verifica vc su un cammino base @ F S 1 ;.; S n ; @ G è F wp(g,s 1 ;...;S n ) La sua validità implica che quando F vale prima delle istruzioni del cammino eseguito, allora G vale dopo. Tradizionalmente questa condizione di verifica viene denotata dalla tripla di Hoare: {F}S 1 ;...;S n {G} 34

Esempio: cammino 2 BinarySearch @pre F : 0 l u < a sorted(a,l,u) S 1 : assume l u; S 2 : m := (l+u) div 2; S 3 : assume a[m] = e; S 4 : rv := true; @post G: rv ( i.l i u a[i] = e); La vc è F wp(g,s 1 ;S 2 ;S 3 ;S 4 ) 35

wp(g,s 1 ;S 2 ;S 3 ;S 4 ) Esempio: cammino 2 BinarySearch wp(wp(g,rv := true),s 1 ;S 2 ;S 3 ) wp(wp(g{rv true}, assume a[m] = e),s 1 ;S 2 ) wp(a[m] = e G{rv true},s 1 ;S 2 ) wp(wp(a[m] = e G{rv true},m := (l+u) div 2),S 1 ) wp((a[m] = e G{rv true}){m (l+u) div 2},S 1 ) wp((a[m] = e G{rv true}){m (l+u) div 2}, assume l u) l u (a[m] = e G{rv true}){m (l+u) div 2} 36

Esempio: cammino 2 BinarySearch Applicare le sostituzioni produce l u (a[(l+u) div 2] = e G{rv true,m (l+u) div 2}) Semplificando la vc di conseguenza: (0 l u < a sorted(a,l,u)) (l u a[(l+u) div 2] = e i.l i u a[i] = e) che è valida nella teoria dei numeri e degli array. 37

Correttezza totale La correttezza parziale rappresenta semplicemente un passo per dimostrare la correttezza totale di una funzione di un programma. La correttezza totale di una funzione asserisce che se l input soddisfa la precondizione della funzione, la funzione si fermerà restituendo un output che soddisfa la post condizione della funzione. Quindi, oltre a dimostrare la parziale correttezza della funzione dobbiamo far vedere che la funzione termina sempre per quegli input che soddisfano la precondizione. 38

Correttezza totale La dimostrazione di terminazione di una funzione si basa sulle relazioni ben fondate: si definisca un insieme S con una relazione ben fondata, si trovi una funzione δ che mappa gli stati del programma nell insieme S e che decresce rispetto alla relazione lungo ogni cammino di base. Poiché è ben fondata, non può esistere una sequenza infinita di stati del programma; altrimenti essi sarebbero mappati in una sequenza infinita e decrescente in S. La funzione δ viene detta funzione di ranking. 39

Esempio di correttezza totale: cammino BinarySearch @pre u l+1 0 @post u l+1 bool BinarySearch(int [] a, int l, int u, int e) { if (l > u) return false; else { int m := (l+u) div 2; if (a[m] = e) return true; else if (a[m] < e) return BinarySearch(a, m+1, u, e); else return BinarySearch(a, l, m 1, e); } } 40

Esempio di correttezza totale: cammino BinarySearch u l+1 mappa i parametri formali di BinarySearch nell insieme dei numeri naturali N con la relazione ben fondata <. L intervallo [l,u] si riduce ad ogni livello di ricorsione e quindi u l potrebbe essere una buona scelta come funzione di ranking. Tuttavia potrebbe accadere che l > u così che u l non venga mappato in N. Pertanto, poiché sarà al più l = u+1, è preferibile porre u l+1. 41

Esempio di correttezza totale: cammino BinarySearch Proprietà di u l+1: 1.Poiché, u l+1 è di tipo int, dobbiamo dimostrare che u l+1 viene di fatto mappato in N: tutte le volte che u l+1 viene valutato all entrata della funzione, deve accadere che u l+1 0. 2.Dobbiamo provare che u l+1 decresce ad ogni chiamata ricorsiva. 42

Esempio di correttezza totale: cammino BinarySearch È la precondizione della funzione stessa ad asserire la prima proprietà. Per dimostrare la seconda proprietà riduciamo l argomento ai cammini di base: attraverso ogni cammino di base u l+1 deve decrementare. Prendiamo in considerazione i cammini significativi. 43

Esempio di correttezza totale: cammino BinarySearch Cammino 1: @pre u l+1 0 u l+1 assume l u; m := (l+u) div 2; assume a[m] e; assume a[m] < e; u (m+1)+1 44

Esempio di correttezza totale: cammino BinarySearch Cammino 2: @pre u l+1 0 u l+1 assume l u; m := (l+u) div 2; assume a[m] e; assume a[m] e; u (m+1)+1 Esistono altri cammini di base dall entrata nella funzione fino all uscita (return statement). Tuttavia, poiché entrambi portano alla fine della ricorsione, sono irrilevanti per l argomento di terminazione. 45

Esempio di correttezza totale: cammino BinarySearch I cammini di base che abbiamo mostrato inducono due condizioni di verifica: 1.u l+1 0 l u... u (((l+u) div 2)+1)+1 < u l+1, 2.u l+1 0 l u... (((l+u) div 2) 1) l+1 < u l+1, dove... elide i letterali che coinvolgono a[m] e che sono irrilevanti per l argomento di terminazione. 46