Seu axioma não é realmente um axioma, faltam hipóteses. Apresentações simples da lógica Hoare manipulam fórmulas do formato que e são fórmulas lógicas e é um comando. Você precisa garantir que seja bem formado . Em linguagens simples, como as usadas frequentemente para uma primeira introdução à lógica de Hoare, a boa formação é sintática: normalmente é uma questão de verificar seP P ′ C C C{ P} C{ P′}PP′CCCestá em conformidade com uma gramática livre de contexto e, possivelmente, que as variáveis livres estejam dentro de um conjunto permitido. Se a linguagem incluir construções com correção semântica, como acessos a elementos de matriz, você precisará adicionar hipóteses para expressar essa correção semântica.
Formalmente, você pode adicionar julgamentos para expressar a correção de expressões e comandos. Se as expressões não tiverem efeitos colaterais, elas não precisarão de pós-condições, apenas pré-condições. Por exemplo, você pode escrever regras de boa formação, como
e permite apenas expressões bem formadas nos comandos:
{P[x←E]}
{ P}E wf{ P∧ 0 ≤ E< L e n g t h ( A ) }A [ E] wf{ P}E1 wf{ P}E2 wf{ P}E1+ E2 wf
{ P[ x ← E] }E wf{ P[ x ← E] }x : = E{ P}
Uma abordagem diferente é tratar todas as expressões como bem formadas, mas fazer com que qualquer expressão que envolva um cálculo mal formado tenha um valor especial . Em idiomas com verificação de limites de tempo de execução, significa "este programa gerou uma exceção fatal". Você acompanharia se um programa cometeu algum através de um predicado lógico ; um programa é válido apenas se você puder provar que sua pós-condição implica .
e r r o r E r r o r ¬ E r r o re r r o re r r o rE r r o r¬ E r r o r
{ P[ x ← E] }x : = E{ P∨ E r r o r }P[ x ← E]⟹E↛ e r r o r{ P[ x ← E] }x : = E{ P}
Ainda outra abordagem é considerar um Hoare triplo para manter apenas se o programa terminar corretamente. Essa é a abordagem comum para programas não-determinantes: a pós-condição é mantida quando o comando termina, o que nem sempre pode acontecer. Se você tratar os erros de tempo de execução como sem término, varre todos os problemas de correção por baixo do capô. Você ainda precisará provar a correção do programa de alguma forma, mas ele não precisa estar na lógica de Hoare se você preferir algum outro formalismo para essa tarefa.
A propósito, observe que expressar o que acontece quando uma variável composta, como uma matriz, é modificada, está mais envolvido do que o que você escreveu. Suponha era, digamos, : a substituição não mudaria , ainda a atribuição pode invalidar . Mesmo se você restringir a sintaxe dos predicados para falar apenas sobre átomos, considere a atribuição na pré-condição : você não pode fazer uma substituição simples para obter a pós-condição correta , é necessário avaliarI s S o r t e d ( A ) Uma [ i ] ← E P Uma [ i ] ← P P A [ A [ 0 ] - 1 ]PI s S o r t e d (A)A [ i ] ← EPA [ i ] ← PPA [ 0 ] = 2 ∧ Um [ 1 ] = 3 A [ 0 ] = 1 ∧A [ A [ 0 ] - 1 ] : = A [ 0 ]A [ 0 ] = 2 ∧ A [ 1 ] = 3A [ 0 ] A [ 0 ] A ← A [ i ← E ]A [ 0 ] = 1 ∧ A [ 1 ] = 1A [ 0 ](o que pode ser difícil em geral, pois a pré-condição pode não especificar um único valor possível para ). Você precisa executar a substituição no próprio array: . As notas de aula de Mike Gordon apresentam uma boa lógica de Hoare de apresentação com matrizes (mas sem verificação de erro).A [ 0 ]A ← A [ i ← E]
length
aA
?length
foi renomeadoA_length
.) Segundo, precisamos de axiomas de "criação" de array comoint[] a = int[length] {a_length==length}
. Eu acho que isso deve ser suficiente.