u+1=v é realmente uma pós-condição do loop while (por que você acha que “claramente” não é o caso?). Esse é sempre o caso de um loop while que não contém a break
: quando o loop sai, isso pode ocorrer apenas porque a condição do loop (aqui, ) é falsa. Não é a única coisa que será verdadeira quando o loop terminar aqui (esse algoritmo realmente calcula algo interessante, como você viu em sua classe, então e também são pós-condições), mas é o mais óbvio.u+1≠vu=[this interesting thing]v=[this interesting thing]
Agora, para encontrar outras propriedades interessantes, não há receita geral. De fato, existe algum sentido formal em que não há receita geral para encontrar invariantes de loop. O melhor que você pode fazer é aplicar algumas técnicas que só funcionam em alguns casos ou, geralmente, procurar observações interessantes (que funcionam cada vez melhor à medida que você fica mais experiente).
Se você executar o loop para algumas iterações com algum valor de , verá isso em cada iteração:n
- quer salta para ;u(u+v)/2
- ou pula para .v(u+v)/2
Em particular, começa com menos de nunca o ultrapassará. Além disso, começa positivo e aumenta, enquanto começa em e diminui. Portanto, é invariável ao longo deste programa.uvuvn+10≤u≤v≤n+1
Uma coisa que não é tão óbvia é se pode ser igual a . Isso é importante: se e se tornarem iguais, teremos e o loop continuará para sempre. Portanto, você precisa provar que e nunca se tornam iguais para provar que o algoritmo está correto (ou seja, não faz um loop para sempre). Depois que essa necessidade é identificada, é fácil provar (estou deixando isso como um exercício) que é um loop invariável (lembre-se de que e são números inteiros, portanto isso é equivalente a ).uvuvx=u=vuvu<vuvu+1≤v
Como no final do programa, a pós-condição que você recebeu também pode ser escrita (a parte é trivial). A razão pela qual queremos uma pós-condição como essa, envolvendo , é que queremos vincular o resultado do programa à entrada . Por que essa condição precisa? Estamos procurando por algo o mais preciso possível e observamos onde aparece dentro do loop:v=u+1u2≤n<v20≤u2nnn
- nós temos ;u≤x≤v
- quando , escolhemos o próximo como , de modo que (e não muda);u x u 2 ≤ n vx2≤nuxu2≤nv
- quando , escolhemos o próximo como , de modo que (e não muda).v x n < v 2 ux2>nvxn<v2u
Essa dicotomia sugere que talvez o tempo todo. Em outras palavras, suspeitamos que seja um loop invariável. Verificar isso é um exercício para o leitor (lembre-se de verificar se a propriedade é verdadeira inicialmente).u2≤n<v2
E agora que fizemos tudo isso, vemos que e : é a raiz quadrada de arredondada para o número inteiro mais próximo.( u + 1 ) 2 > n u nu2≤n(u+1)2>nun