u + 1 = v è in effetti una post-condizione del ciclo while (perché pensi che sia "chiaramente" non il caso?). Questo è sempre il caso di un ciclo while che non contiene un break
: quando il ciclo termina, può essere solo perché la condizione del ciclo (qui, ) è falsa. Non è l'unica cosa che sarà vera quando il ciclo esce qui (questo algoritmo in realtà calcola qualcosa di interessante, come hai visto nella tua classe, quindi e sono anche post-condizioni), ma è il più ovvio.u + 1 ≠ vu = [questa cosa interessante]v = [questa cosa interessante]
Ora, per trovare altre proprietà interessanti, non esiste una ricetta generale. In effetti, esiste un certo senso formale in cui non esiste una ricetta generale per trovare invarianti a ciclo continuo. Il meglio che puoi fare è applicare alcune tecniche che funzionano solo in alcuni casi, o generalmente andare a pescare per osservazioni interessanti (che funziona sempre meglio man mano che diventi più esperto).
Se esegui il ciclo per alcune iterazioni con un valore di , vedrai che ad ogni iterazione:n
- sia salti fino a ;u(u+v)/2
- oppure passa a .v(u+v)/2
In particolare, inizia meno di e non lo supererà mai. Inoltre, inizia positivo e aumenta, mentre inizia da e diminuisce. Quindi è un invariante in tutto questo programma.v u v n + 1 0 ≤ u ≤ v ≤ n + 1uvuvn+10≤u≤v≤n+1
Una cosa che non è così ovvio è se può mai essere uguale a . Questo è importante: se e diventano mai uguali, avremo e il ciclo continuerà per sempre. Quindi è necessario dimostrare che e non diventano mai uguali al fine di dimostrare che l'algoritmo è corretto (ovvero che non esegue il loop per sempre). Una volta identificata questa necessità, è facile dimostrare (lo sto lasciando come esercizio) che è un invariante di loop (tieni presente che e sono numeri interi, quindi questo equivale a ).v u v x = u = v u v u < v u v u + 1 ≤ vuvuvx=u=vuvu<vuvu+1≤v
Poiché alla fine del programma, la post-condizione che ti è stata data può anche essere scritta (la parte è banale). Il motivo per cui vogliamo una post-condizione come questa, che coinvolga , è che vogliamo legare il risultato del programma con l'ingresso . Perché questa precisa condizione? Stiamo cercando qualcosa che sia il più preciso possibile e osserviamo dove appare all'interno del loop:v=u+1u2≤n<v20≤u2nnn
- abbiamo ;u≤x≤v
- quando , scegliamo il prossimo come , in modo che (e non cambi);x2≤nuxu2≤nv
- quando , scegliamo la prossima come , in modo che (e non cambi).x2>nvxn<v2u
Questa dicotomia suggerisce che forse sempre. In altre parole, sospettiamo che sia un loop invariante. La verifica di ciò viene lasciata come esercizio al lettore (ricorda di verificare inizialmente che la proprietà sia vera).u2≤n<v2
E ora che abbiamo fatto tutto questo, vediamo che e : è la radice quadrata di arrotondata per difetto all'intero più vicino.( u + 1 ) 2 > n u nu2≤n(u+1)2>nun