Semântica
Conceitos Semântica é o estudo do significado. Incide sobre a relação entre significantes, tais como palavras, frases, sinais e símbolos, e o que eles representam, a sua denotação.
Semântica Operacional A ideia existente por trás da semântica operacional é descrever o significado de um programa ao executar suas instruções em uma máquina, seja ela real ou simulada. As alterações que ocorrem no estado de uma máquina quando ela executa determinada instrução, definem o significado desta.
Para entender o conceito considere uma instrução de linguagem de máquina. Digamos que o estado de um computador sejam os valores de todos os seus registradores e de suas localizações de memória, inclusive códigos de condição e registro de status. Ao se registrar o estado do computador, executar uma determinada instrução e depois examinar o novo estado da máquina, a semântica será clara: ela é representada pela mudança no estado do computador, causada pela execução da instrução.
Exemplo: exp1 for(exp1; exp2; exp3) loop if exp2>=5 goto out {...... exp3; } goto loop out
Avaliação A semântica operacional constitui um meio efetivo de descrever a semântica para usuários e para implementadores da linguagem, contanto que as descrições mantenham-se simples e informais. A semântica operacional depende de algoritmos, não da matemática. As instruções de uma linguagem de programação são descritas em termos das instruções de uma de nível mais baixo. Essa abordagem pode levar a circularidades, em que os conceitos são indiretamente definidos em termos de si mesmos.
Semântica Axiomática Princípio evidente por si mesmo, particularmente em matemática. O matemático grego Euclídes definiu o axioma como uma noção comum, ou seja, uma afirmação geral aceita sem discussão. Um exemplo de axioma é: "a parte é menor que o todo".
Semântica Axiomática A semântica axiomática foi definida em conjunto com o desenvolvimento de um método para provar a exatidão dos programas que mostra a computação descrita por sua especificação, quando pode ser construída. Em uma prova, cada instrução de um programa tanto é precedida como seguida de uma expressão lógica que especifica restrições a variáveis.
Semântica Axiomática Estas, em vez do estado inteiro de uma máquina abstrata, são usadas para especificar o significado da instrução. A notação usada para descrever restrições, na verdade a linguagem da semântica axiomática, é o cálculo de predicado. Ainda que expressões booleanas simples sejam frequentemente adequadas para expressar restrições, em alguns casos não o são.
Asserções A semântica axiomática baseia-se na lógica matemática. As expressões lógicas são chamadas predicados ou asserções. Uma asserção que precede imediatamente uma instrução de programa descreve as restrições de variáveis dele nesse ponto. Uma asserção que se segue imediatamente a uma instrução descreve as novas restrições a essas variáveis depois da execução da instrução.
Asserções Essas asserções são denominadas pré-condição e póscondição, respectivamente, da instrução. O desenvolvimento de uma descrição axiomática ou prova de determinado programa exige que toda instrução tenha uma pré-condição e uma pós-condição.
Exemplo: Consideremos que as pré-condições para instruções são computadas partindo de determinada pós condição. soma = 2*x+1 {soma > 1}
Pré-condições mais fracas Aquela que é a menos restritiva que garantirá a validade da pós-condição associada. Para o exemplo anterior qualquer valor de x> 100, 50 ou 10 seria válido, e a pré-condição mais fraca seria x>0, note que 2*1+1 = 3
Instruções de Atribuição Digamos que x=e seja uma instrução de atribuição geral, e Q sua pós-condição. Então sua pré-condição, E é definida pelo axioma P=Qx-> E Significando que P é computado como Q com todas as instâncias de x substituídas por E.
Exemplo: a= b/2-1 {a<10} Qual é a pré-condição mais fraca?
Exemplo: a= b/2-1 {a<10} Qual é a pré-condição mais fraca? {b<22}.
Instruções de Atribuição A pré condição é calculada da seguinte forma: 2*y 3 > 25 y > 14 Então {y>14} é a pré-condição mais fraca para essa instrução de atribuição e de pós-condição. x = x + y - 3 {x>10} y>13 x
Aplicando Agora que conhecemos a teria, vamos a prática, como o axioma para instruções de atribuição pode ser usado para provar alguma coisa? Quando aplicamos à pós-condição e a instrução gera a pré-condição daa, o teorema está provado
Exemplo: {x>3} x = x 3 {x>0} Aplicando o teorema temos: x = x-3 {x>0} {x>3}
Exemplo: {x>5} x = x 3 {x>0} Aplicando o teorema temos: x = x-3 {x>0} {x>3}
{x>5} x = x 3 {x>0} Exemplo: Aplicando o teorema temos: x = x-3 {x>0} {x>3} Ora, {x>5} é tão válido, embora seja mais forte que {x>3}
Para usarmos isso em uma prova, precisaremos de uma regra de inferência, chamada regra de consequência. A forma geral de uma regra de inferência é: S1.S2...Sn S Aplicando a qual estabelece que se S1, S2... e Sn forem verdadeiros, a verdade S poderá ser inferida.
Aplicando A forma da regra de consequência é: {P} S {Q}. P => P, Q =>Q {P } S {Q} O Símbolo => significa implica S pode ser qualquer instrução lógica.
Aplicando A regra pode ser enunciada da seguinte maneira: se a instrução lógica {P} S {Q} for verdadeira e a asserção P implica a asserção P e a asserção Q implica a asserção Q, pode-se inferir que {P} S {Q}. Agora usaremos para a prova anterior a regra de consequência. {x>3} x = x 3 {x>0}, {x>5} => {x>3}, {x>0} => {x>0} {x>5} x = x 3 {x>0}
Aplicando A regra pode ser enunciada da seguinte maneira: se a instrução lógica {P} S {Q} for verdadeira e a asserção P implica a asserção P e a asserção Q implica a asserção Q, pode-se inferir que {P} S {Q}. Agora usaremos para a prova anterior a regra de consequência. {P} S {Q} {P } {P} {Q} {Q } {x>3} x = x 3 {x>0}, {x>5} => {x>3}, {x>0} => {x>0} {x>5} x = x 3 {x>0} {P } {S} {Q}
Sequencias A pré-condição mais fraca de uma sequência de instruções não pode ser descrita por meio de um axioma porque depende dos tipos particulares de instruções da sequência. Neste caso, a pré-condição somente pode ser descrita com uma regra de inferência.
Sequências Considere S1 e S2 instruções de programa adjacentes. Se S1 e S2 tiverem as seguintes pré-condições: {P1} S1 {P2} {P2} S2 {P3} A regra de inferência para esta sequência de duas instruções será: {P1} S1 {P2}, {P2} S2 {P3} {P1} S1;S2 {P3}
Sequências {P1} S1;S2{P3} descreve a semântica axiomática da sequência S1; S2. Se S1 e S2 forem instruções de atribuição x1 = E1 e x2 = E2 Teremos {P3x2->E2} x2 = E2 {P3} Portanto, a pré-condição mais fraca para a sequência x1 =E1; x2 = E2 com a pós condição P3 é: {(P3x2->E2)x1->E2}
Exemplo: 1) y = 3 * x + 1 2) x = y + 3 {x < 10} A pré-condição da segunda atribuição é y < 7 Essa será a pós-condição para a primeira. A précondição para a primeira instrução de atribuição agora poderá ser calculada. 3 * x + 1 < 7 x<2
Seleção Consideremos em seguida a regra de inferência para instruções de seleção. Consideremos somente as seleções que incluem cláusulas else. A regra de inferência será {B and P} S1 {Q}, {(not B) and P} S2 {Q} {P} if B then S1 else S2 {Q}
Seleção Consideremos em seguida a regra de inferência para instruções de seleção. Consideremos somente as seleções que incluem cláusulas else. A regra de inferência será {B and P} S1 {Q}, {(not B) and P} S2 {Q} {P} if B then S1 else S2 {Q}
Seleção Essa regra indica que as instruções de seleção devem ser provadas para ambos os casos. A primeira instrução lógica acima da linha é a cláusula then; a segunda é a clausula else.
Exemplo: if ( x > 0) then y = y -1 else y = y > 1
if ( x > 0) then y = y -1 else y = y > 1 Exemplo: Suponhamos que a pós-condição para essa instrução de seleção seja {y > 0}. Podemos usa o axioma para a atribuição na cláusula then.
if ( x > 0) then y = y -1 else y = y > 1 Exemplo: Suponhamos que a pós-condição para essa instrução de seleção seja {y > 0}. Podemos usa o axioma para a atribuição na cláusula then. y = y -1 {y > 0}
Exemplo: Isso produzirá {y -1 > 0} ou simplesmente {y > 1}.
Exemplo: Isso produzirá {y -1 > 0} ou simplesmente {y > 1}. Aplicaremos agora à cláusula else y = y + 1 {y > 0}
Exemplo: Isso produzirá {y -1 > 0} ou simplesmente {y > 1}. Aplicaremos agora à cláusula else y = y + 1 {y > 0} Isso Produzirá a pré condição {y + + 1 > 0} ou {y > -1}. Uma vez que {y > 1} => {y > -1}, a rega de consequencia, nos permite usar {y > 1} para a pré-condição da instrução de seleção.
Lações de Pré-teste Lógico: Outra construção fundamental de uma linguagem de programação imperativa é o laço de pré-teste lógico, ou laço while.
Lações de Pré-teste Lógico: Outra construção fundamental de uma linguagem de programação imperativa é o laço de pré-teste lógico, ou laço while. O problema de computar a pré-condição mais fraca para laços é similar ao problema de provar um teorema sobre todos os números inteiros.
Lações de Pré-teste Lógico: Outra construção fundamental de uma linguagem de programação imperativa é o laço de pré-teste lógico, ou laço while. O problema de computar a pré-condição mais fraca para laços é similar ao problema de provar um teorema sobre todos os números inteiros. Como se provar?
Indução O passo principal será encontrar uma hipótese O passo correspondente na semântica axiomática de um laço while é encontrar uma asserção chamada invariante de laço.
Indução A regra de inferência para computar a pré-condição para um laço é: (I and B) S {I} {I} while B do S end {I and (not B)} I é o invariante do laço
Indução A descrição axiomática de um laço while é escrita como: {P} while B do S end {Q}
Indução Invariante
Indução Invariante A pré-condição mais fraca para o while deve garantir a verdade da invariante do laço
Indução Invariante A pré-condição mais fraca para o while deve garantir a verdade da invariante do laço. Deve garantir a verdade da pós-condição após a finalização do laço.
Indução Invariante A pré-condição mais fraca para o while deve garantir a verdade da invariante do laço. Deve garantir a verdade da pós-condição após a finalização do laço. Durante a execução do laço, a verdade da invariante do laço não deve ser afetada pela avaliação da expressão booleana que controla o laço.
Lações de Pré-teste Lógico: A descrição axiomática completa de uma construção exige que tudo que segue seja verdadeiro sendo I invariante. P=>I {I} B {I} {I and B} S {I} {i and(not B)} => Q
Lações de Pré-teste Lógico: Como encontrar o invariante?
Lações de Pré-teste Lógico: Como encontrar o invariante? Usamos a pós-condição de laço Q para computar pré-condições para diversos números de iterações do corpo do laço, iniciando com nenhum.
Lações de Pré-teste Lógico: Como encontrar o invariante? Usamos a pós-condição de laço Q para computar pré-condições para diversos números de iterações do corpo do laço, iniciando com nenhum. wp(instrução, pós-condição) = pré-condição.
Exemplo 1: while y < x do y = y+1 end {y = x} A pré-condição mais fraca é {y = x}
Para uma iteração Exemplo 1: wp(y = y + 1, {y = x} )= {y + 1 = x}, ou {y = x-1}
Exemplo 1: Para uma iteração wp(y = y + 1, {y = x} )= {y + 1 = x}, ou {y = x-1} Para duas iterações wp(y = y + 1, {y = x-1} )= {y + 1 = x-1}, ou {y = x-2}
Exemplo 1: Para uma iteração wp(y = y + 1, {y = x} )= {y + 1 = x}, ou {y = x-1} Para duas iterações wp(y = y + 1, {y = x-1} )= {y + 1 = x-1}, ou {y = x-2} Para três iterações wp(y = y + 1, {y = x-2} )= {y + 1 = x-2}, ou {y = x-3}
Exemplo 1: Para uma iteração wp(y = y + 1, {y = x} )= {y + 1 = x}, ou {y = x-1} Para duas iterações wp(y = y + 1, {y = x-1} )= {y + 1 = x-1}, ou {y = x-2} Para três iterações wp(y = y + 1, {y = x-2} )= {y + 1 = x-2}, ou {y = x-3} Basta {y<x} para uma ou mais iterações ou simplesmente {y<=x}
Exemplo 1: {I and B} S {I} {y <=x and y<>x} y = y +1 {y <=x} y = y + 1 {y <= x} {y+1<=x} que é equivalente a {y < x}
{I and (not B)} => {Q} Exemplo 1: {(y<=x) and (not(y<>x))} => {y = x} {(y<=x) and (y=x)} => {y=x} {y=x} => {y=x}
A finalização do laço Exemplo 1: {y <= x} while y<x do y = y + 1 end{y=x}
Exemplo 2: {n >= 0} cont = n fatorial = 1 while cont > 0 do fatorial = fatorial * cont cont = cont -1 end {fatorial = n!}
Invariante? Exemplo 2:
Invariante? Exemplo 2: fatorial = (cont +1) * (cont +2) *...* (n-1) *n
Invariante? Exemplo 2: fatorial = (cont +1) * (cont +2) *...* (n-1) *n AND (cont >=0)
Condições: {I and B} S {I} Exemplo 2: ((fatorial = (cont +1)*...*n AND (cont >=0)) AND (cont <>0) (fatorial = (cont +1)*...*n ) AND (cont >0)
Condições: {I and (not B)} => {Q} Exemplo 2: ((fatorial = (cont +1)*...*n AND (cont >=0)) AND (cont =0) => fatorial = n!
Avaliação: Para definir a semântica de uma linguagem completa usando o método axiomático, um axioma ou uma regra de inferência deve ser usado para cada tipo de instrução. Semântica axiomática e uma ferramenta poderosa para pesquisar provas de exatidão de programas.