Dimostrazioni, induzione e invarianti
In questa pagina 4
Servono per le analisi di complessità e di correttezza (l'algoritmo termina e risolve il problema computazionale, vedi Problemi computazionali e algoritmiProblema computazionale come insieme di coppie (istanza, soluzione); algoritmo e modello di calcolo RAM; pseudocodice; taglia di un'istanza; ADT e struttura dati concreta; esempio svolto con ricerca lineare e binaria in un array ordinato.Problemi computazionali e algoritmi →).
Esempio, controesempio, assurdo
- Esempio: per dimostrare che basta mostrare che per ogni abbastanza grande esiste un'istanza che richiede almeno operazioni (vedi Complessità in tempo e caso pessimoPerché lo studio sperimentale non basta; complessità al caso pessimo come massimo sul numero di operazioni tra le istanze di una data taglia; stima con limiti superiore e inferiore senza trovare l'istanza peggiore; esempi arrayMax, prefixAverages e InsertionSort; efficienza asintotica e limiti dell'analisi.Complessità in tempo e caso pessimo →).
- Controesempio: per confutare " è primo per ogni " basta .
- Assurdo: si nega la tesi e si ottiene una contraddizione. Se è dispari, allora e sono dispari: se uno fosse pari, ad esempio , allora sarebbe pari, contro l'ipotesi.
Induzione
Per provare che vale per ogni :
- si sceglie (di solito );
- base: si dimostra ;
- passo: si fissa arbitrario e, assumendo vera per ogni con (ipotesi induttiva), si dimostra .
Il passo deve valere per ogni . Servono più casi base quando il passo usa più valori precedenti (Fibonacci usa i due precedenti: ).
Esempio 1. per . Base : . Passo: . ✓
Esempio 2 (Fibonacci). , , . Si prova con , . Base: (verifica diretta). Passo (): . Si osserva , perché ; allo stesso modo per . Quindi . ✓ (Verificato numericamente: .)
Esempio 3. : . Passo: . ✓
Correttezza di un algoritmo
Schema generale: si individuano lo stato iniziale e quello finale desiderato, si scompone l'algoritmo in segmenti con uno stato atteso a fine segmento (checkpoint) e si prova che dallo stato iniziale si raggiungono in successione tutti i checkpoint; l'ultimo deve implicare lo stato finale. I segmenti notevoli sono i cicli. La terminazione si prova assicurandosi che cicli e ricorsione abbiano fine.
Invarianti di ciclo
Un invarianteProprietà sulle variabili del ciclo che descrive lo stato a ogni iterazione. è una proprietà delle variabili usate nel ciclo che:
- vale all'inizio del ciclo, come conseguenza dello stato iniziale (inizializzazione);
- vale alla fine di ogni iterazione, assumendo che valesse all'inizio di quella iterazione (conservazione);
- alla fine dell'ultima iterazione, insieme alla condizione di uscita, implica la correttezza del ciclo (uso).
Un ciclo esegue iterazioni del corpo; for i <- 1 to n ne fa sempre .
arrayMax. currMax <- A[0]; for i <- 1 to n-1 do currMax <- max(currMax, A[i]). Invariante: alla fine dell'iterazione , . All'inizio ( prima del ciclo) = massimo di . Conservazione: il massimo di è il massimo tra il massimo di e . Alla fine () è il massimo di tutto l'array.
Il più lungo segmento di 1 in una sequenza di bit :
max <- 0; curr <- 0
for i <- 1 to n do
if S[i] = 1 then
curr <- curr + 1
if curr > max then max <- curr
else curr <- 0
return maxInvariante alla fine dell'iterazione : (a) è la lunghezza del segmento di 1 che termina in (zero se ) e (b) è la lunghezza massima di un segmento di 1 in . Inizio (): sequenza vuota, entrambi . Conservazione: se il segmento che termina in estende quello che terminava in , quindi cresce di 1 e viene aggiornato se lo supera; se il segmento si interrompe e , mentre non cambia. Fine: per la (b) dà la risposta. (Controllato con un test casuale su sequenze di lunghezza .)
Cicli con due indici (esempio d'esame): in while (i < n) AND (j < m) su una matrice con colonne decrescenti, l'invariante lega il valore corrente a e ; si veda l'esercizio Esercizio 3 · invariante su matrice a colonne decrescenti.
Errori comuni
- Un invariante che vale solo alla fine (non è un invariante): deve valere anche all'inizio e dopo ogni iterazione.
- Un invariante troppo debole: non basta a concludere la correttezza all'uscita (es. "" non dice che sia il massimo).
- Nell'induzione: provare il passo solo per un specifico, o dimenticare uno dei casi base quando il passo usa due valori precedenti.
- Confondere ipotesi induttiva e tesi: nel passo si assume per e si prova .
Versione ripasso
- Tecniche: esempio (per un : basta un' istanza cattiva), controesempio, assurdo (nego la tesi e trovo una contraddizione).
- Induzione su : base ; passo: ipotesi per , tesi , per ogni . Fibonacci: , , passo con . Gauss: ; .
- Correttezza: stato iniziale checkpoint stato finale; cicli e ricorsione devono terminare (vedi Problemi computazionali e algoritmiProblema computazionale come insieme di coppie (istanza, soluzione); algoritmo e modello di calcolo RAM; pseudocodice; taglia di un'istanza; ADT e struttura dati concreta; esempio svolto con ricerca lineare e binaria in un array ordinato.Problemi computazionali e algoritmi →).
- Invariante di ciclo: (1) vale prima del ciclo; (2) se vale prima di un'iterazione, vale dopo; (3) a fine ciclo implica la tesi. arrayMax: dopo l'iterazione , . Segmento di 1: = lunghezza del segmento che termina in , = massima lunghezza in .
- Schema per i cicli: (1) inizializzazione: l'invariante vale prima della prima iterazione; (2) conservazione: se vale all'inizio di un'iterazione, vale alla fine; (3) uso: alla fine, con la condizione di uscita, implica la tesi.
for i <- 1 to nfa sempre iterazioni. - Esempi di invariante:
arrayMax: dopo l'iterazione , ; segmento di 1: = segmento che termina in , = massimo in . - Induzione di Gauss: .
- Errori: invariante vero solo a fine ciclo o troppo debole; passo induttivo non per ogni ; casi base mancanti; confondere ipotesi e tesi.