Sempre existem infinitamente muitos invariantes de loop válidos. O truque é encontrar um que seja suficiente para provar o que você quer provar sobre o algoritmo e que você pode provar (geralmente por indução sobre o número de iterações de loop).
Existem três partes para provar a correção desse algoritmo:
- O algoritmo nunca executa uma etapa incorreta. Aqui, as possíveis etapas incorretas são acessar um elemento da matriz fora dos limites da matriz.
- Quando o algoritmo retorna
YES
ou NO
, esta saída está correta.
- O algoritmo termina para cada entrada.
Para correção, você precisa provar que e . É melhor fazer parte do seu invariante. Dada a condição do loop , você pode condensar isso em na entrada no corpo do loop. Esta condição não é verdadeiro quando o teste de circuito é atingido no final, mas que pode vir a ser útil para aviso de que (porque no interior do corpo do ciclo, com , e alterar apenas por , que pode na pior das hipóteses, transformar essa desigualdade estrita em igualdade).1≤i≤n1≤j≤ni<j1≤i<j≤ni≤ji<jij1
Quando return YES
é executado, é aparente. Portanto, esta parte não precisa de nada em particular para ser provado.A[i]+A[j]=b
Quando a última return NO
instrução é executada, o que significa que o loop terminou normalmente (e, portanto, é falso), você precisa provar que . Esta propriedade obviamente não é verdadeira em geral: não se aplica se a resposta for . Você precisa fortalecer essa propriedade: você tem um caso especial, que precisa ser generalizado. Este é um caso típico de uma propriedade que se aplica apenas à parte da matriz que já foi percorrida: o loop é construído para que se seja um valor anterior de (ou seja, e e ) em seguidai<j∀i,∀j,A[i]+A[j]≠bYES
(x,y)(i,j)1≤x≤ij≤y≤n(x,y)≠(i,j)A[x]+A[y]≠b . É melhor que isso seja expresso no loop invariável.
Nós terminamos lá? Não é bem assim; tudo o que sabemos sobre a terminação normal do loop é que . E se tivéssemos e , ou e : poderíamos ter ? É difícil dizer sem mais informações. De fato, é melhor distinguir alguns casos em que e os casos em que . Com essas propriedades, podemos usar o fato de que a matriz é classificada para deduzir fatos sobre outras posições na matriz; com apenas , não temos nada para trabalhar. Não sabemos para que lado∀x≤i,∀y≤j,A[x]+A[y]≠bx>iy≤jx≤iy>jA[x]+A[y]≠bA[x]+A[y]>bA[x]+A[y]<b≠bA[x]+A[y]mentiras para alguns e aleatórios ; mas sabemos o que acontece no limite: se é incrementado, é porque é muito pequeno e se é diminuído, é porque é muito grande . Pense em qual laço invariável poderia expressar isso; Vou dar uma possibilidade abaixo.x<iy>jiA[i]+A[j]jA[i]+A[j]
Observe que essa propriedade não fornece diretamente a condição desejada para a return NO
instrução; você ainda precisará observar o que aconteceu na última execução do loop ou, alternativamente, para provar um invariante de loop mais forte que analisa mais de perto quando quando .A[x]+A[y]<bA[x]+A[y]>b
Finalmente, para a terminação, é necessário relacionar e com o número de iterações através do laço. Aqui, isto é simples: ou se move a cada turno, então diminui em cada iteração do loop; você não precisa usar um loop invariável para provar isso.ijijj−i1
Obtivemos o seguinte invariante:
1≤i≤j≤n∧(∀x<i,∀y<j,A[x]+A[y]≠b)∧(∀x<i,A[x]+A[j]<b)∧(∀y>j,A[i]+A[y]>b)