Lógica e Computação
A Lógica proporciona um enquadramento formal para descrever e analizar com rigor um determinado assunto.
O objetivo principal deste texto é apresentar a Lógica como uma ferramenta para a descrição e análise de sistemas informáticos.
Sintaxe e Semântica
Por formal entende-se o tipo de regras, por exemplo, da aritmética ou da sintaxe de programas. Uma expressão aritmética como tem uma estrutura que segue um conjunto de definições sintáticas, que determinam o que pode ser escrito.
- Por exemplo é uma expressão incorreta porque não respeita as definições habituais das expressões aritméticas (porém segue a reversed polish notation).
Por outro lado, o valor resulta de definições semânticas. Por exemplo
- A igualdade diz que as expressões e têm o mesmo valor.
- As expressões e são diferentes, porque começam por símbolos diferentes, e .
- Mas ambas definem o mesmo valor.
- Outras igualdades deste tipo, como ou permitem deduzir, por fim, que .
- As definições sintáticas especificam o que pode ser escrito, ie as expressões corretas.
- As definições semânticas definem o valor das expressões corretas.
Dedução
Também interessa a noção de dedução: quais são as conclusões de hipóteses dadas?
Em termos práticos:
- Quais são as consequências de certas ações?
- Se qual o valor de ?
- Quais são os meios necessários para um dado objetivo?
- Qual o valor de quando ?
Este interesse vai além da aritmética. Em geral, como é que a estrutura e o valor permitem chegar a conclusões a partir de hipóteses dadas?.
Uma dedução ou prova é uma sequência de passos que começa com hipóteses e termina numa conclusão. Cada um desses passos deve depender apenas das hipóteses e dos passos anteriores, pela aplicação de regras rigorosas.
Hipóteses, passos e conclusão são proposições (ou fórmulas) e as regras definem como certas proposições (ou fórmulas) são conclusão de outras.
A distinção entre estrutura e valor leva a dois tipos de consequência:
- A consequência sintática diz que há uma prova da conclusão a partir das hipóteses .
- A consequência semântica diz que a conclusão é verdadeira sempre que as hipóteses são verdadeiras.
No primeiro caso, a consequência sintática, não participam os valores verdade/falso. Só é considerada a estrutura da proposições.
Para a consequência semântica interessam os valores verdade/falso e, também, a estrutura. Por exemplo, usando para verdade e para falso, na tabela
os valores booleanos na coluna dependem dos valores / de e de e também da estrutura de ; a coluna é diferente porque, embora dependa exatamente dos mesmos valores, tem uma estrutura diferente.
Informática
No caso da informática a descrição e a análise rigorosa de um sistema (ou programa) é fundamental.
Dado o seguinte programa:
#![allow(unused)] fn main() { fn answer(x: i32) -> i32 { 2 * x } let y = answer(21); println!("The answer is {y}."); }
Os termos usados, como fc
, println!
ou os parêntesis {
, }
não são arbitrários; têm de ser exatamente aqueles e não outros. Além disso, a ordem por que são escritos também segue regras precisas. Por exemplo, o fragmento
#![allow(unused)] fn main() { answer() {fn} 2 * x i32 i32; }
é incorreto.
Além das regras de escrita para programas corretos, também é necessário rigor na execução de um programa. O programa acima deve produzir o texto 42
na consola.
Estes dois aspetos dos programas, a escrita (sintaxe) e a execução (semântica), têm de ser definidas rigorosamente num sistema formal.
A lógica é esse sistema, capaz de definir formalmente tanto a sintaxe como a semântica dos programas.
Além de correto, um programa deve ter um comportamento bem definido. Consideremos a seguinte função:
#![allow(unused)] fn main() { fn sum(x: i32) -> i32 { // x >= 0 let mut y = 0; let mut z = 0; while z !== x { z = z + 1; y = y + z; } // y = 0 + 1 + ... + x y } }
Como garantir que o valor devolvido por sum(x)
é quando ?
Uma resposta formal a este problema também permite considerar as seguintes questões:
- Como definir um programa correto?
- Como descrever o comportamento de um programa?
- Como provar que um programa funciona de acordo com as especificações?
- Como desenvolver componentes adicionais?
- Como analizar e tratar situações críticas, de erro, entradas incorretas, etc?
- Como coordenar equipas de dezenas, centenas ou milhares de engenheiros informáticos, com experiências e formações variadas?
Estas questões não podem ser respondidas ad hoc. Precisam de respostas obtidas com rigor e objetividade.
Um sistema informático crítico não pode ter uma estrutura ambígua ou subjetiva; tem de ser descrito objetivamente de forma a que diferentes equipas o possam analizar, utilizar, desenvolver, corrigir, manter, expandir, substituir, etc
Por exemplo, a documentação de uma linguagem, como a rust
, de uma biblioteca, como a Distributed
, a especificação de um formato, como o yaml
, formalizam o que se pode escrever e o respetivo comportamento.
Esquema de Programa
Para concretizar o objetivo deste curso o programa segue os seguintes assuntos:
- A lógica proposicional é relativamente simples e flexível para descrever alguns domínios simples. No entanto tem limitações que limitam o seu uso em casos reais.
- A lógica de primeira ordem é significativamente mais expressiva e resolve muitas das limitações da lógica proposicional. Essa expressividade vem à custa de alguma complexidade e limites computacionais.
- A verificação de programas ilustra uma aplicação da lógica à informática:
- Dada a especificação formal do comportamento de um programa, como deduzir com rigor que o programa funciona como pretendido?