Alfabetos, Palavras e Linguagens
Era uma vez, num reino muito muito distante, ...
Símbolos e Alfabetos
Alfabeto, Símbolo. Um alfabeto é um conjunto finito de símbolos, também designados letras (em inglês: symbols, letters, tokens).
Os alfabetos são normalmente representados por maiúsculas gregas (sigma) e (gama) e os símbolos por minúsculas romanas .
Por exemplo:
- O alfabeto do português tem os seguintes símbolos: .
- Os símbolos e formam um alfabeto binário. Outro alfabeto binário muito usado em ALP é .
- Os números naturais podem ser escritos em base 10 usando o alfabeto .
- Para as expressões algébricas usa-se o alfabeto .
As linguagens de programação têm um conjunto de palavras reservadas, como
while
,if
, etc. que são atómicas, isto é, não podem ser divididas.O símbolo "
if
" não é, em termos da linguagem de programação, um "i
" seguido de um "f
", mas um símbolo que não pode ser decomposto.Já fragmentos de programas como
if (x == 42) { return "yes"; } else { return "no"; }
são compostos. Nesta instrução condicional(x == 42)
é o teste (ou guarda),{ return "yes"; }
o bloco positivo e{ return "no"; }
o bloco negativo. Neste caso a instrução resulta de uma regra do tipo
Condicional := if ( Condição ) { Instruções } else { Instruções }
Por sua vez a guarda (
Condição
) e os blocos deInstruções
podem ser decompostos, até chegarmos a símbolos atómicos como(
,==
,return
, etc.
Palavras
Palavra. Uma palavra sobre um alfabeto é uma sequência finita de símbolos desse alfabeto (em inglês: word).
Formalmente, uma palavra de comprimento é uma função que a cada inteiro .
As palavras são normalmente representadas pelas minúsculas romanas .
Palavra Vazia. A palavra vazia (em inglês: empty word, null, nil) é a única palavra de comprimento 0 e representa-se pela letra grega (lambda). Também é comum usar-se ou (epsilon) para representar a palavra vazia.
Não confundir a palavra (que tem comprimento 0) com um símbolo. Estes, como palavras, têm comprimento um.
Propriedades do Comprimento das palavras
- O comprimento da palavra é normalmente representado por .
- Para a palavra vazia, . Em geral, se então . Isto é, .
Fecho de Kleene
Dado um alfabeto, interessa considerar todas as palavras que podem ser formadas com essas letras.
Por exemplo, para representar números em binário usam-se palavras sobre . Mas, depois de se definirem todas as palavras, há que determinar quais as que interessam. Por exemplo, embora e sejam palavras binárias (distintas), se interpretadas normalmente, ambas correspondem ao número e portanto há aqui uma ambiguidade. Será possível definir uma linguagem que continue a representar todos os números mas sem ambiguidades?
Para abordar estas questões tem de se começar por definir rigorosamente o conjunto de todas as palavras que se podem obter com um dado alfabeto.
Fecho de Kleene. O fecho do alfabeto é o conjunto de todas as palavras sobre , representa-se por e fica definido pelas seguintes condições:
- base .
- passo Se e então .
- fecho Qualquer palavra só pode ser obtida por um número finito de aplicações do passo a começar na palavra vazia. E reciprocamente, qualquer palavra obtida a partir de por aplicações do passo em número finito está em .
Esta definição exclui a possibilidade de palavras infinitas. Mas isto não significa que exista um limite ao comprimento das palavras em . Pelo contrário, se então, para qualquer existe pelo menos uma palavra de comprimento .
Exercício: Porquê? E porque é que acima é referida a condição ""? O que é ?
No fecho de um alfabeto também ficam excluídas palavras formadas por símbolos de outros alfabetos. Por exemplo, a palavra não está em .
Logo a primeira condição na definição de inclui a palavra vazia. Como muitas vezes é conveniente excluir define-se
Exercício: Mostre que .
Operações com Palavras
Comprimento
Ainda não foi apresentada uma definição rigorosa de comprimento de uma palavra. Usando um esquema recursivo:
Comprimento. A função comprimento é calculada pelas seguintes regras:
- base .
- passo , com .
Por exemplo, para calcular :
- Como , aplicar-se a regra do passo: fazendo tem de ser e , e obtem-se .
- Ainda não está calculado o valor de . Tornando a aplicar o passo: .
- Uma nova aplicação do passo: .
- Finalmente, pela base: , portanto e, sucessivamente, obtém-se e .
Também é comum usar-se a notação para indicar o número de ocorrências do símbolo na palavra .
Por exemplo: .
Concatenação
O operação fundamental das palavras é a "concatenação". A concatenação de hello
com world
é helloworld
. Para definir rigorosamente esta operação:
Concatenação. A concatenação (ou produto) de duas palavras representa-se por ou apenas e é uma operação binária definida por:
- base Se então .
- passo Se então
- Existe uma palavra e uma letra tal que .
- .
Por exemplo, para calcular a concatenação de com :
- O comprimento de é 2, portanto temos de aplicar o passo: .
- Precisamos de calcular . Pela regra do passo: .
- Finalmente, é calculada pela regra base: .
- Andando para trás: e, portanto, .
Potência
A repetição de concatenações define as potências, tal como a multiplicação dos números.
Potências. As potências da palavra são (informalmente):
Por exemplo, mas , seguindo as regras normais de precedência das operações.
Inversa
Finalmente, as palavras (enquanto sequências de símbolos) podem ser escritas "de trás para a frente":
Inversa. A inversa de , representada por (ou ) é calculada pelas seguintes regras:
- base Se então .
- passo Se então e .
Por exemplo, se então .
Propriedades das Operações de Palavras
O que acontece à inversa de duas palavras concatenadas?
Para quaisquer palavras ,
Demonstração (informal): Se a conclusão é evidente. Caso contrário e com todos os . Então:
O fecho também tem propriedades interessantes.
Se forem alfabetos,
- .
- .
- .
- Se então é infinito.
- Se então .
Por fim, a concatenação tem propriedades semelhantes às do produto (de números).
Sejam .
- associativa .
- elemento neutro .
- não comutativa Em geral, .
- aditiva .
- unicidade Cada palavra só pode ser escrita de uma única forma como concatenação de símbolos. Isto é, se e e então (mesmo comprimento) e para cada (mesmos símbolos) .
Ordenações de Palavras
Uma palavra pode "conter" outra. Por exemplo, palavra
contém pala
no início, ala
no "meio" e lavra
no fim. Estes três casos ilustram as definições que se seguem:
Subpalavra, prefixo, sufixo. Sejam .
- subpalavra se .
- prefixo se .
- sufixo se .
Fica claro que os prefixos são casos particulares das subpalavras (quando ) e que cada palavra é subpalavra de si própria (quando ).
Outro caso importante é a ordem lexicográfica (dos dicionários), onde se usa a ordem das letras para ordenar as palavras.
Ordem Lexicográfica. Supondo que o alfabeto está ordenado, . Então se:
- .
- Caso contrário, e com .
Esta definição abrange dois casos:
por < porque
porquepor
é um prefixo deporque
.porque < portugal
porque, comoporque = por_q_ue
eportugal = por_t_ugal
entãoportugal
eporque
têm um prefixo comum,por
, e "divergem primeiro" nas letrasq
et
. Comoq < t
entãoporque < portugal
.
A ordem lexicográfica tem um problema interessante: Quantas palavras existem entre e , num alfabeto binário?
Por exemplo [Exercício: porquê?]. Mas também . De facto, para qualquer . Portanto, seguindo a ordem lexicográfica, há infinitas palavras entre e .
Esta conclusão, embora dramática, mostra que a ordem lexicográfica é inútil na importante tarefa de enumerar (isto é, listar) todas as palavras por ordem. Para resolver este problema é necessária mais uma ordem entre palavras:
Ordem Mista. Dadas duas palavras , se ou ( e ).
Dito de outra forma, a ordem mista define o seguinte processo:
- Primeiro, as palavras são agrupadas por comprimentos iguais: todas as palavras de comprimento 0 antes das de comprimento 1, todas as de comprimento 1 antes das de 2, etc.
- Depois, em cada grupo, as palavras (todas com o mesmo comprimento) são ordenadas lexicograficamente.
Revisitando o exemplo anterior:
- e têm o mesmo comprimento. Portanto, são comparadas lexicograficamente: porque .
- O comprimento de é maior que o de . Portanto, .
- e têm o mesmo comprimento. Lexicograficamente, portanto .
De facto a ordem mista é uma ferramenta essencial porque permite "avançar passo-a-passo" no conjunto de todas as palavras, sem deixar nenhuma de fora. Mais concretamente:
A ordem mista define uma sequência de todas as palavras. No caso do alfabeto binário, com :
Sucessor
A ordem mista permite começar na primeira palavra, avançar para a seguinte, depois para a seguinte, etc. da mesma forma são contados os números: 0, 1, 2, etc.
A passagem de um número para o seguinte (x++
) tem nome, sucessor, que também se aplica às palavras:
Sucessor. Seja um alfabeto ordenado. A função sucessor tem assinatura e calcula-se pelas seguintes regras:
- base .
- passo Se então . Caso contrário, .
Voltando ao exemplo anterior:
Visto de outra forma, usando o sucessor obtém-se uma sequência que começa na palavra vazia e percorre todas as palavras:
Há uma clara relação entre a ordem mista e a função sucessor.
Seja a sequência de todas as palavras de que se obtém com a ordem mista e uma palavra qualquer.
- .
- Se então existe uma palavra tal que .
- .
O que este teorema afirma, especialmente na igualdade , é que a ordem mista e a função sucessor são aspetos diferentes da mesma enumeração das palavras.
Linguagens
Numa linguagem de programação nem todas as palavras possíveis correspondem a programas válidos. Por exemplo:
2 return) *
: dobro def (x
é uma palavra que pode ser formada com o alfabeto do python
, mas não é um programa.
É necessário, de alguma forma, distinguir as palavras que são "válidas" das outras que não o são. De novo, encontramos na matemática exatamente as ferramentas necessárias.
Linguagem. Uma linguagem é um conjunto de palavras sobre um certo alfabeto. Isto é, é uma linguagem sobre se .
Esta definição de linguagem parece dizer pouco, mas por enquanto serve exatamente para o que se pretende.
Por exemplo, se for a linguagem dos programas python
então mas .
Mais tarde será enunciado e tratado o Problema Principal de ALP:
Problema Principal de ALP (versão 0). Dada uma linguagem e uma palavra no mesmo alfabeto, determinar se .
Entretanto, como uma linguagem é (apenas) um conjunto de palavras, tem um certo número de elementos, que pode ser infinito (quantos programas python
existem?): Se for uma linguagem, representa o número de elementos de .
Outros exemplos de linguagens são:
- binárias , , etc.
- As palavras do português, sobre o alfabeto romano. Por exemplo,
a
,aba
,abade
, etc. mas nãoaa
,prof
,tásse
,xkcd
, etc. - Os programas de uma linguagem de programação.
- As frases do português, sobre o alfabeto formado pelas palavras do português. Por exemplo
bom dia
,a aula é longa
, etc. mas nãodia dia dia
,aula a é longa
, etc.
Muitas vezes é útil visualizar-se uma linguagem de forma a explorar a estrutura das suas palavras. Isso pode ser feito através de árvores:
Árvore de uma Linguagem. Seja uma linguagem sobre .
Os vértices (ou nós) da árvore de (ou diagrama de ) são palavras de e cada aresta (ou arco) tem um símbolo de . Além disso, todas as arestas são da seguinte forma: se e então é uma aresta. A raíz da árvore é a palavra vazia.
Cada vértice é representado por um círculo com a respetiva palavra lá dentro. Uma palavra da linguagem é representada por um círculo duplo.
Por exemplo, tem a seguinte árvore (onde os vértices irrelevantes foram omitidos):
Árvore (parcial) de |
---|
As palavras de estão em círculos duplos. |
Operações com Linguagens
Como conjuntos, as linguagens podem ser combinadas pelas operações comuns: união, intersecção, etc. Além disso, como os seus elementos são palavras, podem ser definidas operações adicionais, específicas das linguagens (concatenação, fecho, etc).
Operações com Linguagens. Sejam linguagens sobre . Estão definidas as seguintes operações de conjuntos:
- união .
- intersecção .
- subtração .
- complemento .
Adicionalmente, usando as operações de palavras:
- concatenação .
- potências .
- fechos .
- inversão .
Alguns exemplos das operações específicas das linguagens: Sejam . Então:
- .
- As palavras de foram formadas escolhendo primeiro uma palavra de e depois uma palavra de .
- A palavra pode ser obtida de suas formas: e .
- .
- .
- .
Confusões com a palavra vazia, o conjunto vazio, etc.
- A palavra vazia, , não é um símbolo. Qualquer símbolo, como palavra, tem comprimento 1. A palavra vazia tem comprimento 0.
- O conjunto vazio, , tem 0 elementos. Para tornar este facto mais explícito também se escreve .
- O conjunto tem um elemento, . Portanto, não é o conjunto vazio.
Exemplo. Aqui (e só no âmbito deste exemplo) estamos a distinguir explicitamente os símbolos usando plicas, como em 'a'
, e as palavras usando aspas, como em "ab"
.
- O alfabeto
{a, b}
tem dois símbolos:'a'
e'b'
. - Uma palavra é uma (qualquer) sequência finita de símbolos.
- Por exemplo
"abba"
,"baba"
,"aa"
, etc.
- Por exemplo
- Todas as palavras de comprimento 2 são
"aa"
,"ab"
,"ba"
,"bb"
. - Também poderíamos listar todas as palavras de comprimento 3 (num total de oito palavras), etc.
- Todas as palavras de comprimento 1 são
"a"
e"b"
.- Se quiséssemos ser terrivelmente rigorosos, teríamos de dizer que
'a'
e"a"
são diferentes porque'a'
é um símbolo e"a"
é uma sequência de símbolos, tal como, por exemplo, o inteiro1
é completamente diferente de[1]
, que é uma lista de inteiros. - Raramente é necessário distinguir explicitamente os símbolos das palavras de comprimento um.
- Se quiséssemos ser terrivelmente rigorosos, teríamos de dizer que
- Só há uma palavra com comprimento zero. Como sequência,
""
é a (única) com zero símbolos. Em vez de""
escreve-seλ
(ouε
ouϵ
).λ
não é um símbolo mas uma palavra. Escrita por extenso é""
.
- Usando a concatenação de palavras podemos escrever, por exemplo:
"abba" = "ab" · "ba"
.- Outras formas de obter
"abba"
são"abba" = "a" · "bba"
,"abba" = "abb" · "a"
, etc. - Em particular também
"abba" = "abba" · λ
ou"abba" = λ · "abba"
ou mesmo"abba" = λ · "a" · λ · "bba"
. - Nestes exemplos o
λ
nunca aparece entre"..."
pois isso é o equivalente a um erro sintático. Também não escrevemos2 */ 3
quando fazemos contas...
- Outras formas de obter
- Em geral não se escrevem os símbolos como
'a'
, as palavras como"abab"
nem as concatenações como"aa" · "ba"
.- Portanto, em vez de
"abba" = λ · "a" · λ · "bba"
o que escrevemos é simplesmenteabba = λaλbba
. - Este abuso de notação pode facilitar a leitura errada de
λ
como um símbolo, à semelhança dea
eb
.
- Portanto, em vez de