Apostila LFA.pdf

60
UNIVERSIDADE ESTADUAL DO MATO GROSSO DO SUL CURSO DE CIÊNCIA DA COMPUTAÇÃO APOSTILA DE AULA DISCIPLINA DE LINGUAGENS FORMAIS E AUTÔMATOS Professora Viviane Duarte Bonfim Lages, Agosto de 2009.

Transcript of Apostila LFA.pdf

Page 1: Apostila LFA.pdf

UNIVERSIDADE ESTADUAL DO MATO GROSSO DO SUL

CURSO DE CIÊNCIA DA COMPUTAÇÃO

APOSTILA DE AULA

DISCIPLINA DE LINGUAGENS FORMAIS E AUTÔMATOS

Professora Viviane Duarte Bonfim

Lages, Agosto de 2009.

Page 2: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

2

SUMÁRIO

1. SISTEMAS FORMAIS, GRAMÁTICAS E MODELOS ABSTRATOS DO COMPUTADOR ........... 5

1.1 Sistemas Formais ................................................................................................................................ 5

1.2 Origem Sistemas Formais ................................................................................................................... 5

1.3 Métodos Formais ................................................................................................................................. 6

1.4 Linguagens Formais ........................................................................................................................... 6

1.5 Gramáticas ......................................................................................................................................... 10

1.5.1 Definição Formal de Gramática .................................................................................................. 11

1.5.2 Derivação e Redução .................................................................................................................... 12

1.5.3 Notação ......................................................................................................................................... 13

1.5.4 Linguagens Definidas por Gramáticas ........................................................................................ 13

1.5.5 Sentença, Forma Sentencial e Linguagem .................................................................................. 14

1.6 Tipos deLinguagens/ Gramáticas ..................................................................................................... 14

1.7 Tipos de Linguagens – Representação gráfica ................................................................................. 15

2. LINGUAGENS REGULARES ................................................................................................................. 16

2.1 Operações de Concatenação e Fechamento ..................................................................................... 16

2.1.1. Definição de Expressões Regulares ............................................................................................. 17

2.2. AUTÔMATOS FINITOS ........................................................................................................................ 18 2.2.1. Autômatos Finitos Determinísticos .............................................................................................. 18

2.2.2. Autômatos Finitos Não-Determínisticos ...................................................................................... 20

2.2.3. Transformação de A.F.N.D. para A.F.D. .................................................................................... 21

2.2.4. Relação entre G.R. e A.F. ............................................................................................................. 22

2.2.5. Minimização de Autômatos Finitos: ............................................................................................ 25

2.2.6. Aplicações de A.F. e E.R. ............................................................................................................. 27

3. GRAMÁTICAS L IVRES DE CONTEXTO .................................................................................................... 29

3.1. SIMPLIFICAÇÕES DE GRAMÁTICAS L IVRES DE CONTEXTO ............................................................. 29 3.1.1. Símbolos Inúteis ........................................................................................................................... 29

3.1.2. Eliminação de εεεε-produções .......................................................................................................... 30

3.1.3. Produções Unitárias ..................................................................................................................... 30

3.1.4. Eliminação de Recursão à Esquerda ........................................................................................... 31

3.1.5. Fatoração à Esquerda .................................................................................................................. 31

3.2. CONJUNTOS FIRST E FOLLOW .......................................................................................................... 32 3.2.1. Conjunto First ............................................................................................................................... 32

3.2.2. Conjunto Follow ........................................................................................................................... 33

3.3. AUTÔMATOS COM PILHA .................................................................................................................. 33 3.3.1. Modelagem de MEF’s como SD’s ................................................................................................ 35

4. TEORIA DA COMPUTAÇÃO - TEORIA DE PROBLEMAS: DECIDIB ILIDADE, COMPUTABILIDADE E COMPLEXIDADE .................... ............................................................................. 37

4.1. INTRODUÇÃO ..................................................................................................................................... 37

4.1.1. Conceitos e Propósitos Fundamentais da Teoria da Computação .............................................. 38

4.2. TEORIA DE PROBLEMAS .................................................................................................................... 41 4.2.1. Solucionabilidade de Problemas .................................................................................................. 41

4.2.2. Decidibilidade ............................................................................................................................... 41

4.2.3. Princípio da Resolução de Problemas .......................................................................................... 42

4.2.4. Classes de Solucionabilidade de Problemas ................................................................................ 42

4.2.5. Definição Formal de Problema .................................................................................................... 43

4.2.6. Modos de Definir uma Função .................................................................................................... 45

4.3. COMPUTABILIDADE ........................................................................................................................... 46 4.3.1. Origem da Computabilidade ......................................................................................................... 46

4.3.2. Computabilidade de Funções ....................................................................................................... 49

4.3.3. Problema da Parada ..................................................................................................................... 50

4.3.4. Exemplo Problemas Não Computáveis ........................................................................................ 54

4.3.5. Computabilidade Parcial .............................................................................................................. 55

4.3.6. Complexidade ................................................................................................................................ 56

4.3.7. Recursos Computacionais ............................................................................................................ 56

4.3.8. Problemas Tratáveis e Intratáveis ................................................................................................ 58

Page 3: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

3

4.3.9. Modelo Formal de Algoritmo: Máquina de Turing .................................................................... 59

REFERÊNCIAS BIBLIOGRÁFICAS............................................................................................................... 60

Page 4: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

4

INTRODUÇÃO

Teoria de Linguagens Formais e Teoria de Máquina são práticas abrangentes que se inserem

no estudo da Teoria da Computação em geral. A teoria da Computação é uma ciência que procura

organizar o conhecimento formal relativo aos processos de computação, como complexidade de

algoritmos, linguagens formais, problemas intratáveis.

Atualmente, o termo “computar” está associado ao conceito de fazer cálculos ou aritmética,

usando para isso máquinas computadoras. Entretanto, a noção de computabilidade pode ser

dissociada da implementação física da máquina. Originalmente a palavra latina putare significa

“pensar”, mas no caso da teoria da computação o sentido mais adequado seria algo como

“manipulação de símbolos”, o que não é necessariamente, pensamento. Essa manipulação de

símbolos envolvendo, principalmente letras, números e proposições algébricas permitiriam às

máquinas computadoras, segundo Alan Turing (1939) realizar qualquer operação formal de que o ser

humano seria capaz.

Mesmo assim, alguns filósofos sustentavam que os computadores não poderiam computar

(fazer aritmética), porque não compreende a noção de número (apenas manipulam sinais elétricos).

Todavia, pode-se falar, sem entrar no mérito da questão, que os computadores realizam uma

“computação perceptível”, já que transforma uma entrada em saída como se estivessem realmente

computando. Neste caso, o que importa é o efeito final do processo e não a maneira como ele é

realizado.

Page 5: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

5

1. Sistemas Formais, Gramáticas e Modelos Abstratos do Computador

1.1 Sistemas Formais

São Sistemas de manipulação de formas, sem preocupação de que estas formas significam no

mundo real.

A essência de um Sistema Formal é a Sintaxe.

Semântica – escrever de maneira correta – lexicograficamente.

Sintaxe: escrita na ordem correta. Manipula símbolos.

Ex. 15::=Resultado+10 (erro) – passaria pelo bloco léxico pois os tokens estão escritos de

maneira correta. Mas não passaria no bloco sintático.

1.2 Origem Sistemas Formais

A primeira notícia de que se tem de um sistema formal são os trabalhos de Euclides (300A.C.).

Estes trabalhos organizam e sistematizam todo o conhecimento da época com relação à Geometria e

são conhecidos sob nome de Elementos. Pela primeira vez, a apresentação é feita através de axiomas,

definições, postulados, teoremas e demonstrações.

O arcabouço básico dos Sistemas Formais é devido a René Descartes (1596-1650) e de

Leibniz (1646-1716) sobre linguagens e alfabetos. Frege (1848-1925), Peano (1858-1932), Whitehead

(1861-1947), Bertran Russel (1872-1970) e Wittgenstein (1889-1951) criaram a formalização como se

costuma apresentar.

Na construção de um Sistema Formal deve-se concentrar atenção na forma com que se

trabalha. As Linguagens Naturais, aquelas usadas entre seus seres humanos para se comunicarem

possuem ambigüidades que impedem seu uso para este propósito. Portanto, torna-se necessário, dar

um passo na direção de evitar estas ambigüidades o que é feito usando uma linguagem constituída por

um conjunto bem definido de símbolos e de regras de derivação, permitindo construir novos objetos a

partir daqueles disponíveis.

Page 6: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

6

1.3 Métodos Formais

Podem ser aplicados em diversos domínios, dependendo do contexto. São técnicas com

fundamentos matemáticos usados para descrever e analisar propriedades de Sistemas. Um dos

motivos de usar métodos formais é avaliar ou eliminar as ambigüidades e inconsistências na

especificação. Normalmente cada método formal está associado a uma linguagem formal. A

Linguagem formal possui sua sintaxe e sua semântica bem definidas.

É possível provar que um programa, ou parte dele, sempre termina em um tempo finito.

1.4 Linguagens Formais

O que é a Teoria das Linguagens Formais?

Para responder esta questão precisa-se primeiro responder o que é Linguagem Formal, e para

isto precisamos antes responder o que é Linguagem.

Inicialmente, de maneira bastante informal, podemos definir uma linguagem como sendo uma

forma de comunicação. Elaborando um pouco mais esta definição, podemos definir uma linguagem

como sendo “um conjunto de elementos (símbolos) e um conjunto de métodos (regras) para combinar

estes elementos, usado e entendido por uma determinada comunidade”.

Exemplos: 1 - Linguagens Naturais (ou idiomáticas)

2 - Linguagens de Programação, de Controle, de Consulta

3 – Protocolos de Comunicação

Contudo, apesar de intuitiva, esta definição não nos permite responder satisfatoriamente as

duas primeiras questões; precisamos antes dar um sentido formal para a definição de linguagem.

Faremos isto nas duas próximas seções.

O estudo dos diversos tipos de linguagens aplica-se a diversas áreas de informática, sempre

que for necessário analisar o formato e o significado de uma seqüência de entrada.

O estudo das linguagens formais, sob a forma de gramáticas é a base da teoria da

interpretação e compilação. A decisão de uma seqüência constitui uma unidade válida para a

linguagem é baseada em regras definidas.

O nome Teoria de Linguagens Formais é devido a que regras para uma linguagem devem ser

explicitamente definidas em termos de quais seqüências ou cadeias (“strings”) podem ocorrer. O

estudo de linguagens formais objetiva como “especificar” um conjunto de cadeias para uma

determinada linguagem.

Page 7: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

7

Conceitos Básicos:

Linguagem Formal: é o conjunto de palavras sobre um alfabeto.

� Um Alfabeto é definido simplesmente como um conjunto finito de símbolos. Por exemplo,

o alfabeto da língua portuguesa é V = {a, b, c, d..., z}. O alfabeto utilizado para expressar

os números naturais é V = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}.

� Um Símbolo é uma entidade abstrata que não precisa ser definida formalmente, assim

como “ponto” e “linha” não são definidos na geometria. Letras e dígitos são exemplos de

símbolos freqüentemente usados.

Símbolos são ordenáveis lexicograficamente e, portanto, podem ser comparados quanto à

sua igualdade. Por exemplo, tomando as letras do alfabeto, pode-se Ter a ordenação a < b

< c < ...< z. A utilidade dos símbolos está na possibilidade de usá-los como elementos

atômicos em definições de linguagens.

� Uma sentença sobre um alfabeto V, é uma seqüência (ou cadeia) finita de símbolos do

alfabeto.

Exemplo de sentenças sobre V = { a , b }: a, b, aa, ab, bb, aaa, aab, aba, baa, ...

� Tamanho de uma sentença: Seja w uma sentença ∀.

O tamanho da sentença w, denotado por |w|, é definido pelo número de símbolos

(elementos do alfabeto) que compõem w.

Exemplos: Seja V = { a , b , c }

se x = aba, então |x| = 3

se x = c, então |x| = 1

� Sentença vazia é uma sentença constituída de nenhum símbolo; isto é, uma sentença de

tamanho 0 (zero).

Observações: Representa-se a sentença vazia por ε (épsolon).

- Por definição, |ε| = 0

Page 8: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

8

� Uma Cadeia é uma seqüência finita de símbolos justapostos (sem vírgula separando os

caracteres). Por exemplo, se a, b e c são símbolos, então abcb é um exemplo de cadeia

utilizando estes símbolos.

O tamanho de uma cadeia é o comprimento da seqüência se símbolos que a forma. O

tamanho de uma cadeia w é denotado por |w|. Por exemplo, |abcb| = 4. A cadeia vazia é

denotada por ε., e tem tamanho igual a 0; assim |ε| = 0.

Um prefixo de uma cadeia é um número qualquer de símbolos tomados de seu início, e um

sufixo é um número qualquer de símbolos tomados de seu fim. Por exemplo, a cadeia abc

tem prefixo ε a, ab e abc. Seus sufixos próprios são ε, c, bd, abc. Um prefixo ou sufixo que

não são a própria cadeia são chamados de prefixo próprio e sufixo próprio. No exemplo

anterior, os prefixos próprios são ε, a e ab; e os sufixos próprios são ε, c e bc.

� Potência de uma sentença: Seja w uma sentença ∀. A n-ésima potência de w,

representada por wn, significa w repetido n vezes.

Exemplos: se x = ab, então x3 = ababab

Para ∀ x, x0 = ε

� A Concatenação de duas cadeias é a cadeia formada pela escrita da primeira cadeia

seguida da Segunda, sem nenhum espaço no meio. Por exemplo, a concatenação de

compila e dores é compiladores. O operador de concatenação é a justaposição. Isto é, se

w e x são variáveis que denotam cadeias, então wx é a cadeia formada pela concatenação

de w e x. No exemplo acima, se tornarmos w=compila e x=dores, tem-se compiladores.

� O Fechamento de um Alfabeto V, representado por V*, é o conjunto de todas as cadeias

que podem ser formadas com símbolos de V, inclusive a cadeia vazia. O Fechamento

Positivo de V, denotado por V+ é definido como V* - {ε}. Ou seja, todas as cadeias

formadas com os símbolos de V, exceto a cadeia vazia.

Linguagens e suas representações:

� Uma Linguagem (formal) é um conjunto de cadeias de símbolos tomados de algum

alfabeto. Isto é, uma linguagem sobre o alfabeto V é um subconjunto de V*. Esta definição

não considera-se mecanismos formadores da linguagem, mas apenas a sua extensão.

Page 9: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

9

Assim, por exemplo, o conjunto de sentenças válidas da língua portuguesa poderia ser

definido como um subconjunto de {a, b, c,.., z}+.

� Representações de Linguagens: O estudo de linguagens está intimamente relacionado

ao estudo das formas de representação dessas linguagens. O problema de representação

de uma linguagem, por sua vez, está relacionado com o fato dela ser finita ou infinita:

Linguagem Finita: É uma Linguagem que pode ser representada por enumeração.

Exemplo: A linguagem definida como sendo o conjunto dos inteiros positivos pares

maiores que 0 e menores que 20, pode ser representado por: L = {2, 4, 6, 8, 10, 12, 14, 16, 18}.

Linguagem Infinita: Neste caso, na impossibilidade de usarmos enumeração,

precisamos encontrar uma representação finita para estas linguagens.

Exemplo: A linguagem definida como sendo o conjunto dos inteiros pares poderia ser

representada por V ={2, 4, 6, 8, 10,...} que, que apesar de intuitiva, não é finita e nem precisa.

As representações finitas de linguagens classificam-se em Reconhecedores e Sistemas

Geradores:

� Um Reconhecedor para uma linguagem é um dispositivo formal usado para verificar se

uma determinada sentença pertence ou não a uma determinada linguagem. São exemplos

de reconheceres de linguagens, as Máquinas de Turing, o Autômato de pilha e o

Autômato Finito. Cada um destes mecanismos reconhece um conjunto bastante particular

de linguagens. Entretanto, os modelos são inclusivos: todas as linguagens reconhecíveis

por um Autômato Finito podem ser reconhecidas por um Autômato de Pilha e todas as

linguagens reconhecíveis por um autômato de pilha são reconhecíveis por Máquinas de

Turing.

� Um Sistema Gerador é um dispositivo formal através do qual sentenças de uma

linguagem podem ser sistematicamente geradas. Exemplos de sistemas geradores são as

gramáticas gerativas, definidas pela primeira vez por Noam Chomsky, em seus estudos

para sistematizar a gramática da língua inglesa.

Todo Reconhecedor e todo sistema gerador pode ser representado por algoritmos e/ou

procedimentos. Pode-se garantir que linguagens reconhecidas por autômatos são reconhecidas

algoritmicamente. Já o conjunto das linguagens reconhecidas por Máquinas de Turing, que é mais

Page 10: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

10

abrangente, inclui linguagens reconhecíveis algoritmicamente e linguagens indecidíveis, que não

possuem algoritmos para reconhecimento.

� Linguagens Formais: São linguagens que podem ser representadas de maneira finita e

precisa através de sistemas com sustentação matemática (dispositivos formais ou modelos

matemáticos).

Obs: Entende-se por Teoria das Linguagens Formais e dos Autômatos o estudo de modelos

matemáticos que possibilitam a especificação e o reconhecimento de linguagens (no sentido amplo da

palavra), suas classificações, estruturas, propriedades, características e inter-relacionamentos.

A importância desta Teoria na Ciência da Computação é dupla: Ela tanto apóia outros aspectos

teóricos da Ciência da Computação (decidibilidade, computabilidade, complexidade computacional, por

exemplo), como fundamenta diversas aplicações computacionais tais como processamento de

linguagens, reconhecimento de padrões, modelagem de sistemas.

1.5 Gramáticas

Sabe-se que uma linguagem é qualquer conjunto ou subconjunto de sentenças sobre um

alfabeto, ou seja: dado um alfabeto V, uma linguagem L sobre esse alfabeto, é um subconjunto de V*∴

L ⊆ V*.

Assim sendo, devemos nos preocupar em definir que subconjunto é esse.

A finalidade de uma gramática é definir o subconjunto de V* que forma (define) uma

determinada linguagem. Uma gramática define uma estrutura sobre um alfabeto de forma a permitir

que apenas determinadas combinações sejam válidas, isto é, sejam consideradas sentenças (definindo

assim a linguagem que ela representa).

O que é Gramática?

Uma gramática, de maneira informal, pode ser definida como sendo:

a) Um sistema gerador de linguagens;

b) Um sistema de reescrita;

c) Uma maneira finita de descrever (representar) uma linguagem;

d) Um dispositivo formal usado para especificar de maneira finita e precisa uma linguagem

potencialmente infinita.

Page 11: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

11

Uma gramática gerativa é um instrumento formal capaz de construir (gerar) conjuntos de

cadeias de uma determinada linguagem. As gramáticas são instrumentos que facilitam muito a

definição das características sintáticas das linguagens. São instrumentos que permitem definir, de

forma formal e sistemática, uma representação finita para linguagens infinitas.

Exemplo intuitivo de uma Gramática:

(um subconjunto da gramática da língua portuguesa)

<sentença> :: = <sujeito> <predicado>

<sujeito> :: = <substantivo>

| <artigo> <substantivo>

| <artigo> <adjetivo> <substantivo>

<predicado> :: = <verbo> <objeto>

<substantivo> :: = joão | Maria | cachorro | livro | pão

<artigo> :: = o | a

<adjetivo> :: = pequeno | bom | bela

<verbo> :: = morde | le | olha

<objeto> :: = <substantivo>

| <artigo> <substantivo>

| <artigo> <adjetivo> <substantivo>

Notação utilizada:

< ......... > : categoria sintática ou gramatical;

::= : definido por

| : ou (alternativa)

α ::= β : regra de sintaxe (ou regra gramatical ou regra de produção)

1.5.1 Definição Formal de Gramática

Uma gramática possui um conjunto finito de variáveis (não-terminais). A linguagem gerada por

uma gramática é definida recursivamente em termos de variáveis e de símbolos primitivos chamados

terminais, que pertencem ao alfabeto da linguagem.

Page 12: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

12

As regras que relacionam variáveis e terminais são chamados de produções, que sempre

iniciam num ponto, o símbolo inicial. Uma regra de produção típica estabelece como uma determinada

configuração de variáveis e terminais pode ser reescrita, gerando uma nova configuração.

Uma Gramática é especificada por uma quádrupla (N,T,P,S), onde:

� N é o conjunto de não-terminais, ou variáveis.

� T é o conjunto de terminais, ou alfabeto, sendo que N e T são conjuntos disjuntos (não se

misturam)

� P é um conjunto finito de produções, ou regras, sendo que P⊆(N∪T)+ X (N∪T)*

� S é o símbolo não terminal inicial, sendo S∈N. a partir dele são geradas todas as

sentenças da linguagem.

Uma produção (n,p) pode ser escrita n::=p, para facilitar a leitura. No caso de existir mais de

uma alternativa para uma mesma configuração e símbolos do lado esquerdo da regra, como exemplo:

<substantivo> ::= coisa

<substantivo> ::= cão

<substantivo> ::= pedra

pode-se escrever as opções em uma única produção, separada por |. O mesmo ex. ficaria:

<substantivo> ::= coisa | cão | pedra

O símbolo ::= pode ser lido como “ é definido por” e o símbolo | pode ser lido como “ou”.

1.5.2 Derivação e Redução

São operações de substituição que formalizam a utilização de gramáticas, sendo que:

Derivação: É a operação que consiste em substituir em string (ou parte dele) por outro, de acordo com

as produções das gramáticas em questão, no sentido símbolo inicial → sentença;

Uma gramática pode ser usada para gerar um linguagem através de reescrita ou derivação.

Ex. dada uma sentença aba; se existir uma regra da forma b::=c, então a sentença inicial pode

ser reescrita como acd. Denotada por:

abd -> acd

Na sentença aaaDbbB e existe a produção D ::= ab na gramática. Então a derivação aaaDbbb

-> aaaabbbb

Redução: É a operação que consiste na substituição de um string (ou parte dele) por outro, de acordo

com as produções da gramática, no sentido sentença → símbolo inicial.

Page 13: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

13

Observação: derivação é a operação adequada para geração de sentenças; enquanto que a operação

de redução é adequada ao reconhecimento de sentenças.

1.5.3 Notação

Como conversão notacional, pode-se admitir que símbolos não-terminais serão sempre

representados por letras maiúsculas, e terminais por letras minúsculas. Assim, uma regra como <a> ::=

<a>b | b poderia ser escrita como A::= Ab | b. Além disso, os conjuntos T e N podem ficar

subentendidos e não precisam ser expressos sempre.

Pode-se ainda arbitrar que o símbolo inicial S será o não-terminal que aparecer primeiro do

lado esquerdo da primeira produção da gramática. Assim, bastaria listar as regras de produção para se

Ter a definição completa da gramática. Por exemplo, a gramática:

S ::= ABSc | ε

BA ::= AB

Bc ::= bc

Ab ::= ab

Bb ::= bb

Aa ::= aa

Tem como símbolo inicial S, o conjunto de terminais é {a, b, c} e o conjunto dos não-terminais

(variáveis) é {A, B, C}. As produções estão detalhadas. Tem-se assim a definição completa da

gramática.

1.5.4 Linguagens Definidas por Gramáticas

A linguagem definida por uma gramática consiste no conjunto de cadeias de terminais que esta

gramática pode gerar. Este conjunto será denotado por L(G). A linguagem definida por uma gramática

G=(N,T,P,S) é dada por:

L(G) = { α| α ∈ T* ∧ S → * α }

Uma cadeia pertence a L(G) se e somente se ela consiste somente de terminais (pode ser a

cadeia vazia ε), e pode ser produzida a partir de S em 0 ou mais derivações.

Forma sentencial se ela pode ser reproduzida a partir de S mas ainda contém não terminais, aaaBbbC.

Já aabb já é uma sentença pois possui apenas terminais.

Page 14: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

14

1.5.5 Sentença, Forma Sentencial e Linguagem

Sentença – É uma seqüência só de terminais produzida (gerada) a partir do símbolo inicial de

uma gramática; isto é, se G = (Vn, Vt, P, S) ∧∧∧∧ S x, então x é uma sentença pertencente à linguagem

representada por G.

Forma Sentencial – É uma seqüência qualquer (composta por terminais e não-terminais)

produzida (gerada) a partir do símbolo inicial de uma gramática; isto é,

se G = (Vn, Vt, P, S) ∧∧∧∧ S ⇒⇒⇒⇒ αααα ⇒⇒⇒⇒ ββββ ⇒⇒⇒⇒ ………… ⇒⇒⇒⇒ γγγγ ⇒⇒⇒⇒ ………… então αααα, ββββ, …………,γγγγ, …………são formas sentenciais de

G.

Linguagem – Formalmente definimos a linguagem gerada por G = (Vn, Vt, P, S), denotada por

L(G), como sendo: L(G) = {x | x ∈∈∈∈ Vt* ∧∧∧∧ S x}; ou seja, uma linguagem é definida pelo conjunto de

sentenças que podem ser derivadas a partir do símbolo inicial da gramática que a representa.

Gramáticas Equivalentes – Duas gramáticas G1 e G2 são equivalentes entre si, se e somente

se L(G1) = L(G2).

Formalmente: G1 ≡≡≡≡ G2 ⇔⇔⇔⇔ L(G1) = L(G2).

Exemplos:

1.6 Tipos deLinguagens/ Gramáticas

Impondo restrições na forma das produções, pode-se identificar quatro tipos diferentes de

gramáticas. Essa classificação foi feita por Chomsky e é conhecida como hierarquia de Chomsky. Os

tipos de gramáticas definidos nesta hierarquia são:

a) Tipo 0: Não há restrição na forma de das produções. É o tipo mais geral. Exemplo:

S ::= ABS | ab Ba ::= aB | a Aa ::= aa | a | ε

b) Tipo 1: Seja G=(N,T,P,S). Se:

� O símbolo Inicial S não aparece no lado direito de nenhuma produção, e

� Para cada produção σ1 ::= σ2

( o nº de símbolos da direita tem que ser igual ou maior o da esquerda)

então se diz que G é uma gramática do tipo 1, ou Gramática Sensível ao Contexto. Exemplo:

S ::= aBC | aABC A ::= AABC | aBC CB ::= BC

aB ::= ab bB ::= bb bC ::= bc cC ::= cc

⇒+

⇒+

Page 15: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

15

c) Tipo 2: Uma Gramática G=(N,T,P,S) é do tipo 2, ou Gramática Livre de Contexto, se cada

produção é livre de contexto, ou seja, cada produção da forma: (No lado esquerdo tem apenas um

símbolo não-terminal.

A ::= σ com A ∈ N e σ ∈ (T ∪ N)*

Exemplo:

S ::= aSb | A A ::= cAd | e

O Tipo 2 não é definido como restrição do tipo 1, porque se permite produções da forma A ::= ε ;

também se permite que o símbolo S apareça no lado direito das produções.

d) Tipo 3: Uma gramática G é do tipo 3, ou regular, se cada produção é da forma A::= aB, A ::= a, A

::= ε, onde A e B são não-terminais e a é um terminal.

(Do lado esquerdo apenas um não terminal, e do lado direito, pode ter o epson, um terminal e um

não-terminal).

Exemplo:

S ::= aS | bB B ::= bB | bC C ::= cC | ε

1.7 Tipos de Linguagens – Representação gráfica

Uma Linguagem L é do tipo i se existe uma gramática G de tipi i tal que L = L(G), para i igual 0,

1, 2, 3.

Pode-se relacionar cada tipo de gramática com uma máquina reconhecedora da seguinte

maneira: a gramática do tipo 0 e 1 gera linguagens reconhecíveis por Máquinas de Turing; a gramática

do tipo 2 gera linguagens reconhecíveis por autômatos de pilha; a gramática do tipo 3 gera linguagens

reconhecíveis por autômatos finitos.

Representação:

Figura 1: Tipos de Linguagens.

Page 16: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

16

2. Linguagens Regulares

As Linguagens Regulares constituem um conjunto de linguagens decidíeis bastante simples e

com propriedades bem definidas e compreendidas. Essas linguagens podem ser reconhecidas por

autômatos finitos e são facilmente descritas por expressões simples, chamadas expressões regulares

(E.). Antes de introduzir o mecanismo das E.R.s, será feito uma revisão sobre operações de

concatenação e fechamento de conjuntos, operações básicas para E.R.s.

2.1 Operações de Concatenação e Fechamento

Seja C um conjunto finito de símbolos (alfabeto), e sejam L, L1 e L2 subconjuntos de C*

(linguagens sobre o alfabeto C). A concatenação de L1 e L2, denotada por L1L2 é o conjunto { xy | x ∈

L1 e y ∈ L2}. Em outras palavras, as cadeias da linguagem L1L2 são formadas por uma cadeia de L1

concatenada a uma cadeia de L2, nesta ordem, incluindo aí todas as combinações possíveis.

Defini-se L0 = {ε} e Ln = LL n-1 para n ≥ 1. O fecho de Kleene ( ou simplesmente fecho) de uma

linguagem L, denotado por L*, é o conjunto:

L* = U Li

e o fecho positivo da linguagem L, denotado por L+, é o conjunto:

L+ = U Li

Em outras palavras, L* denota as cadeias construídas pela concatenação de qualquer número

de cadeias tomadas de L. O conjunto L+ é semelhante, mas neste caso, as cadeias de zero palavras,

cuja concatenação é definida como ε, são excluídas. Nota-se, porém, que L+ contém ε se e somente

se L contém. Esta definição difere da definição do fechamento de alfabetos, onde A+ era definido como

A* - {ε}. No caso da linguagem, pode ocorrer dois casos:

� Se ε ∈ L, então L+ = L*;

� Se ε ∉ L, então L+ = L* - {ε}.

Exemplo:

i = 0

i = 1

Page 17: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

17

1. Seja L1 = {10, 1} e L2 = {0011, 11}. Então L1L2 = {100011, 1011, 10011, 111}

2. {10, 11}* = {ε, 10, 11, 1010, 1011, 1110, 1111,...}

2.1.1. Definição de Expressões Regulares

Seja A um alfabeto. As expressões regulares sobre o alfabeto A e os conjuntos (linguagens)

que elas denotam são definidas indutivamente como segue:

� ∅ é uma expressão que denota o conjunto vazio;

� ε é uma expressão regular que denota o conjunto {ε};

� Para cada símbolo em a em A, a é uma expressão regular que denota o conjunto {a};

� Se r e s são expressões regulares que denotam os conjuntos R e S, respectivamente,

então (r+s), (rs), e (r*) são expressões regulares que denotam os conjuntos R∪S, RS e R*,

respectivamente.

Quando se escreve E.R.s, pode-se omitir muitos parênteses se for assumido que o símbolo *

tem precedência maior que a concatenação e +, e que a concatenação tem precedência maior

que +. Por exemplo: ((0(1*))+0) pode ser escrita como )!* + ). Além disso, pode-se aplicar

simplificações abreviando expressões como rr* para r+.

As E.R.s possuem as seguintes propriedades algébricas:

AXIOMA DESCRIÇÃO

r + s = s + r + é comutativo

r + (s + t) = (r + s) + t + é associativo

(rs)t = r(st) a concatenação é associativa

r(s + t) = rs + RT

(s + t)r = sr + tr

a concatenação é distributiva sobre +

εr = r

rε = r

ε é o elemento neutro (identidade) da

concatenação

r* = (r + ε) relação entre ε e *

Exemplo;

Exercícios;

Tabela 1: Propriedades Algébricas.

Page 18: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

18

2.2. Autômatos Finitos Autômato Finito é um reconhecedor de Linguagens Regulares. Estende-se por reconhecedor

de uma Linguagem L um dispositivo que tomado uma seqüência w como entrada, responde “sim” se w

∈ L e “não” caso contrário.

Os autômatos Finitos classificam-se em:

• Autômatos Finitos Determinísticos (A.F.D)

• Autômatos Finitos Não-Determinísticos (A.F.N.D)

2.2.1. Autômatos Finitos Determinísticos

Formalmente defini-se um A.F.D como sendo um sistema formal M = (Κ, Σ, δ, q0, F), onde:

Κ → É o conjunto finito não-vazio de ESTADOS;

Σ → É um ALFABETO, finto, de entrada;

δ → FUNÇÃO DE MAPEAMENTO ( ou função de transição), definida em Κ x Σ → Κ;

q0 → ∈ Κ, é o ESTADO INICIAL;

F → ⊆ Κ, é o conjunto de ESTADOS FINAIS;

2.2.1.1. Interpretação de δ

A interpretação de δ (q, a) = p, onde {q, p} ∈ K e a ∈ Σ, é de que se o “controle de M” está no

estado “q” e o próximo símbolo de entrada é ä”. Então "a" deve ser reconhecido e o “controle” passa

para o próximo estado (no caso “p”). Nota-se que a função de mapeamento é definida por Κ x Σ → Κ,

ou seja, de um estado, através do reconhecimento de um símbolo, o controle passa para UM ÚNICO

outro estado. Por esse motivo, este autômato é chamado de DETERMINÍSTICO.

Logicamente um estado é uma situação particular no processo de reconhecimento de uma

sentença.

Uma sentença x é aceita (reconhecida) por um A.F.M. = (Κ, Σ, δ, q0, F) se, e somente se, δ (q0, x) = p

∧ p ∈ F.

Uma Linguagem Aceita por Mapeamento é um conjunto de todas as sentenças aceitas por M.

Formalmente, defini-se por:

L(M) = {x | δ (q0, x) = p ∧ p ∈ F}

Page 19: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

19

2.2.1.2. Diagrama de Transição

Um Diagrama de Transição para um A.F.M. é um grafo direcionado e rotulado. Os vértices

representam os estados e fisicamente são representados por círculos, sendo que o estado inicial é

diferenciado por uma seta com rótulo “inicio” e os estados finais são representados por círculos duplos.

As arestas representam as transições, sendo que entre dois estados “p” e “q” existirá uma aresta

direcionada de “p” para “q” com rótulo “a”( a ∈ Σ) ↔ ∃ δ (p, a) = q em M.

2.2.1.3. Tabela de Transição

É uma representação tabular de um A.F.

Nesta tabela as linhas representam os estados (o inicial por uma seta e os finais por

asteriscos). As colunas representam os símbolos de entrada e o conteúdo da posição (q, a) será igual a

“p” se existir δ(q, a) = p, senão será indefinida.

Exemplos:

Abaixo são apresentados dois exemplos de A.F.D nas formas gráficas e tabulares:

Exemplo1: A.F.D que reconheça as sentenças da linguagem L = { (a, b)+, onde o número de a’s é

impar}.

Forma Gráfica:

Início a

b

Forma Tabular:

δ a b

q0 q1 q0

q1 q0 q1

Exemplo2: A.F.D. que reconheça as sentenças da Linguagem l = { (0,1)*, onde todos os 1,s apareçam

consecutivos}.

Forma Gráfica:

Início 1 0

q0 q1

b b

**

q0 q1 q2

0 0 1

Page 20: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

20

Forma Tabular:

δ 0 1

q0 q0 q1

q1 q2 q1

q2 q2 ___

2.2.2. Autômatos Finitos Não-Determínisticos

Um A.F.N.D. é um sistema formal M = (Κ, Σ, δ, q0, F), onde:

Κ, Σ, q0, F → possuem a mesma definição de A.F.D.

δ → é uma função de mapeamento, definida em K x Σ = ρ(K) (um conjunto de estados), sendo que

ρρ(K) é um subconjunto de K. Isto equivale dizer que δ(p, a) = p1, p2,..., pn. A interpretação de δ é que

M no estado “q”, com símbolo “a” na entrada pode ir tanto para o estado p1, como para o estado p2,...,

como para o estado pn.

Exemplo: Seja a Linguagem L = { (a, b)* abb} O A.F.N.D. seria:

Forma Gráfica:

a b b

a, b

Forma Tabular:

δ 0 1

q0 q0, q1 q0

q1 ___ q2

q2 ___ q3

q3 ___ ___

*

***

**

q0 q1 q2 q3

*

Page 21: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

21

2.2.2.1. Comparação entre A.F.D. e A.F.N.D

A tabela abaixo mostra as principais diferenças entre A.F.D e A.F.N.D. :

Vantagens Desvantagens

A.F.D. Implementação Trivial Não apresenta adequadamente

algumas L. R.

A.F.N.D. Representa mais

adequadamente as L. R.

Implementação Complexa

2.2.3. Transformação de A.F.N.D. para A.F.D.

Teorema 4.1: “Seja L um conjunto aceito por um A.F.N.D. , então ∃ um A.F.D. que aceita L”.

Prova: Seja M = (Κ, Σ, δ, q0, F) um A.F.N.D. Construa um A.F.N.M.’ = (K’, Σ’, δ’, q0’, F’) como segue:

� K’ = {ρ(K)} → isto é, cada estado M’ é formado por um conjunto de estados de M.

� q0’ = [q0] → obs: representa-se um estado q ∈ K’ por [q].

� F’ = {ρ(K) | ρ(K) ∩ F ≠ ∅.

� Σ’ = Σ.

� Para cada ρ(K) ⊂ K’, δ’ (ρ(K), a) = ρ’(K) = {p | para algum q ∈ ρ(K), δ(q, a) = p}, ou seja:

SE ρ(K) = [q1, q2,..., qr ∈ K’ e

Se δ( q1, a) = p1, p2, ..., pj

δ( q2, a) = pj+1, pj+2, ..., pK

...

δ( qr, a) = pi, pi+1, ..., pn são as transições de M,

então ρ’(K) = [p1, p2, ..., pj,..., pj, pj+1, , ..., pK, pi, pi+1, pn] será um estado de M’ e M’ conterá a

transição: δ’(ρ(K), a) = ρ’(K).

Para concluir a prova do teorema acima, basta provar que a Linguagem M’ é igual a

Linguagem M(L(M) = L(M’)). Esta prova não será apresentada nesta seção.

Exemplo: Tendo por exemplo o A.F.N.D. já apresentado anteriormente:

δ 0 1

q0 q0, q1 q0

Page 22: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

22

q1 ___ q2

q2 ___ q3

q3 ___ ___

Define M’ = (K’, Σ’, δ’, q0’, F’), onde

δ 0 1

[q0] [q0, q1] [q0]

[q0, q1] [q0, q1] [q0, q2]

[q0, q2] [q0, q1] [q0, q3]

[q0, q3] [q0, q1] [q0]

K’ = {[q0], [q0, q1], [q0, q2], [q0, q3]}

Σ’ = {a, b} q0 = [q0] F’ = [q0, q3]

2.2.4. Relação entre G.R. e A.F.

Teorema 4.2: “Seja G = (N, T, P, S) uma Gramática Regular, então ∃ um A.F.M. = ((K, Σ, δ, q0,

F) | L(M) = L(G)”.

Prova: a) Mostrar que M existe;

b) Mostrar que L(M) = L(G).

a) Define-se M como segue:

1. K = N ∪ {A}, onde A é um novo símbolo não-terminal;

2. Σ = T;

3. q0 = S;

4. F = {B | B → ε P} ∪ {A}, ou seja, todos os estados que produzem ε, juntamente com o novo

estado.

5. Construa δ de acordo com as regras a, b, c:

a) Para cada produção da forma B → a ∈ P, cria-se a transição δ(B, a) = A;

b) Para cada produção da forma B → aC ∈ P, cria-se a transição δ(B, a) = C;

c) Para produções B → ε, não é criada nenhuma transição;

d) Para todo a∈ T, δ(A, a) = -(indefinida)

*

Page 23: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

23

b) Para mostrar que L(M) = L(G), deve-se mostrar que (1) L(G) ⊆ L(M) e (2) L(M) ⊆ L(G). esta

demonstração é fácil, considerando-se as produções as produções da G.R. e a definição das

transições de M, sendo omitida neste texto.

Exemplo:

Dada a gramática regular abaixo, que gera as sentenças da linguagem {(anbm), com n par e m

> 0}, iremos definir um A.F. que reconheça as sentenças desta linguagem.

Gramática: S ::= aA | bB

A ::= aS

B ::= bB | ε

Autômato:

Primeiramente deve-se definir os estados do autômato, com um estado novo, denominado aqui

C. assim, tem-se que K = {S, A, B, C}. O alfabeto é o mesmo, assim Σ = {a, b}, o estado inicial é S, e F

= {B, C}, pela definição acima. Na forma tabular o autômato fica o seguinte:

δ a b

S A B

A S ___

B ___ B

C ___ ___

Nota-se que pode ser gerado um estado inalcançável (o novo estado, quando não houverem

produções da forma B → a, B ∈ N e a ∈ T). Na forma gráfica o autômato fica:

Início

*

*

S

A

B

C

a

b

b

b

Page 24: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

24

Teorema 4.3: “Seja um A.F.M. = (K, Σ, δ, q0, F). Então ∃ uma G.R. G = (N, T, P, S) | L(G) =

L(M)”.

Prova: a) Mostrar que G existe;

b) Mostrar que L(G) = L(M).

a) Seja M = (K, Σ, δ, q0, F) um A.F. Construir uma G.R. G = (N, T, P, S), como segue:

1. N = K;

2. T = Σ;

3. S = q0;

4. Define-se P como segue:

� Se δ(B, a) = C, então adiciona-se B ::= aC em P;

� Se δ(B, a) = C e C ∈ F, então adiciona-se B ::= a em P;

� Se q0 ∈ F, então ε ∈ L(M). Assim a gramática deve ser transformada, encontrando uma outra

G.R., G1, tal que L(G1) = L(G) ∪ {ε}, e L(G1) = L(M). Senão ε ∉ L(M).

b) Para mostrar que L(G) = L(M), deve-se mostrar que (1) L(M) ⊆ L(G) e (2) L(G) ⊆ L(M). Esta prova

também não será expressa aqui neste texto.

Exemplo: Tem-se o seguinte A.F.:

Início

Na forma tabular:

δ a b

S A B

A S C

B C S

C B A

S

A

B

C

a

a

b

b

a

a

b b

*

Page 25: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

25

A G.R. definida pelo exemplo (algoritmo) acima resulta em:

S ::= aA | bB | a

A ::= aS | bC

B :: aC | bS

C ::= aB | bA | b

2.2.5. Minimização de Autômatos Finitos:

Definição: Um A.F.N.D. = (Κ, Σ, δ, q0, F) é MÍNIMO se:

1. Não possuir estados INACESSÍVEIS;

2. Não possui estados MORTOS;

3. Não possui estados EQUIVALENTES;

� Estados Inacessíveis:

Um estado q ∈ K é inacessível quando não existe w tal que a partir de q0, seja alcançado, ou seja,

~∃ w | δ(q0, w) = q, onde w é uma sentença ou parte dela.

� Estados Mortos:

Um estado q ∈ K é morto se ele ∉ F e ~∃ w | δ(q, w) = p, onde p ∈ F e w é uma sentença ou parte

dela. Ou seja, q é morto se ele não é final. E, a partir dele nenhum estado final é alcançado.

� Estados Equivalentes:

Um conjunto de estados q1, q2,..., qj são equivalentes entre sí, se eles pertencem a uma mesma

CLASSE DE EQUIVALÊNCIA.

� Classe de Equivalência:

Um conjunto de estados q1, q2,..., qj estão em uma mesma C.E. se δ(q1, a), δ(q2, a),..., δ(qj, a),

para cada a ∈ Σ, resultam respectivamente nos estados qi, qi+1 ,..., qn e estes pertencem a uma

mesma C.E.

2.2.5.1. Método para Construção do Autômato Finito Mínimo

1. Eliminar os estados inacessíveis;

2. Eliminar os estados mortos;

3. Construir todas as classes de equivalência;

4. Construir M’ como segue:

Page 26: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

26

a) K’ → é o conjunto de C.E. obtidas;

b) q0’ → será a C.E. que contiver q0;

c) F’ → será o conjunto das C.E. que contenham pelo menos um elemento ∈ F, isto é, {[q] |

∃ p ∈ [q] e p ∈ F, onde [q] é um C.E.};

d) δ’ → δ’([p], a) = [q] ↔ δ(p, a) = q é uma transição de M e p e q são elementos de [p] e [q],

respectivamente.

Exemplo: Minimizar o A.F.D. definido na seguinte tabela de transição:

δ’ a b

A G B

B F E

C C G

D A H

E E A

F B C

G G F

H H D

Tem-se que os estados acessíveis são: {A, G, B, F, E, C}. Portanto, pode-se eliminar os

estados D e H. Assim, o novo A.F.D. é:

δ’ a b

A G B

B F E

C C G

E E A

F B C

G G F

Nenhum dos estados do A.F.D. é morto. Assim, pode-se construir as classes de equivalência.

No primeiro passo, duas classes de equivalência são construídas: F e K-F. Cada passo do algoritmo é

representado numa linha da tabela abaixo:

*

*

*

*

Page 27: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

27

F K-F

{A, G} {B, C, E, F}

{A, G} {B, F} {C, E}

{A, G} {B, F} {C, E}

Denominando {A, G} = q0, {B, F} = q1 e {C, E} = q2 , tem-se o seguinte A.F.D. Mínimo:

δ’ a b

q0 q0 q1

q1 q1 q2

q2 q2 q0

2.2.6. Aplicações de A.F. e E.R.

Apesar da simplicidade destas ferramentas, existe uma grande variedade de software cuja

especificação e/ou implementação pode ser bastante simplificada se realizada em termos de A.F. e

E.R., resultando em software´s mais eficientes. Dentre as diversas aplicações que fazem uso de A.F. e

E.R. podemos citar:

a) Analisador Léxico: Os tokens (símbolos básicos) de uma linguagem de programação

geralmente podem ser especificados eficientemente através de E.R., as quais podem ser

automaticamente convertidas para A.F.D. equivalentes, cuja implementação (o analisador léxico

propriamente dito) é trivial.

Isto permite inclusive, a geração automática de um analisador léxico a partir da especificação

formal dos “tokens” de uma linguagem de programação.

b) Editores de Texto: As operações de busca e substituição de cadeias de caracteres em um

texto, podem ser eficientemente realizadas, se a cadeia for expressa em termos de E.R. e a operação

realizada em termos de um A.F. usufruindo da possibilidade da conversão automática de E.R. para

A.F., de forma transparente ao usuário.

c) Além das aplicações acima (tidas como as principais) podemos também destacar o uso

destas ferramentas nas seguintes áreas:

*

Page 28: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

28

c.1) Protocolos de comunicação

c.2) Projeto (modelagem) de sistemas operacionais

c.3) Path Expression

c.4) Problemas específico tais como: segurança de arquivos, desorientação em sistemas

de hipertexto, modelagem de redes neurais, compressão de dados, etc...

Page 29: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

29

3. Gramáticas Livres de Contexto

Uma gramática livre de Contexto (GLC) é denotada por G = (N, T, P, S), onde N e T são

conjuntos disjuntos de varáveis e terminais, respectivamente. P é um conjunto finito de produções,

cada uma da forma A::= α onde A é uma variável do conjunto N e α é uma cadeia de símbolos (N ∪

T)*. S é uma variável especial pelo fato de ser o Símbolo Inicial.

3.1. Simplificações de Gramáticas Livres de Contexto

Existem várias maneiras de restringir as produções de uma gramática livre de contexto sem

reduzir seu poder expressivo. Se L é uma linguagem livre de contexto não-vazia, então L pode ser por

uma gramática livre de contexto G com as seguintes propriedades:

a) Cada variável e cada terminal de G aparecem na derivação de alguma palavra de L.

b) Não há produções da forma A::= B, onde A e B são variáveis.

Além disso, se ε ∉ L, então há necessidade de produções da forma A::= ε.

3.1.1. Símbolos Inúteis

Pode-se eliminar os símbolos inúteis de uma gramática sem prejudicar seu potencial

expressivo. Um símbolo X é útil se existe uma derivação S→* αXβ →* w, para algum w, α e β,

onde w é uma cadeia de T* e α e β são cadeias quaisquer de variáveis e terminais. Caso contrário, o

símbolo X é inútil. Tanto terminais quanto não-terminais podem ser úteis ou inúteis. Se o símbolo inicial

for inútil, então a linguagem definida pela gramática é vazia.

Há dois tipos de símbolos inúteis. Aqueles que não geram nenhuma cadeia de terminais e

aqueles que jamais são gerados a partir de S. O primeiro caso corresponde aos símbolos improdutivos

(ou mortos), e o segundo caso corresponde aos símbolos inalcançáveis. Um terminal sempre é

produtivo, mas pode ser inalcançável. Já o não-terminal pode ser tanto improdutivo como inalcançável.

O algoritmo para eliminação dos símbolos improdutivos é baseado na idéia de que se um não-

terminal A tem uma produção consistindo apenas de símbolos produtivos, então o próprio A é

produtivo.

Exemplo;

Exercícios;

Page 30: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

30

3.1.2. Eliminação de εεεε-produções

Conforme dito, uma GLC pode ter produções do tipo A::= ε. Mas toda GLC pode ser

transformada em uma GLC equivalente sem este tipo de produções (chamadas ε-produções), com

exceção da produção S::= ε, se esta existir (ou seja, a cadeia vazia pertence à linguagem). Assim,

procedendo, é possível mostrar que toda GLC pode obedecer à restrição das GSC (tipo 1). É o método

da eliminação de ε-produções, a qual se tratará.

O método consiste em determinar, para cada variável A em N, se A →* ε. Se isso for verdade,

se diz que a variável A é anulável. Pode-se assim substituir cada produção da forma B::= X1X2...Xn por

todas as produções formadas pela retirada de uma ou mais variáveis Xi anuláveis.

Exemplo;

Exercícios;

Os não-terminais que derivam a sentença ε são chamados de ε-não-terminais. Um não

terminal A é um ε-não-terminal se existir uma derivação A→* ε em G. Note que ε está em L(G) se e

somente se S é um ε-não-terminal. Se G não tem ε-não-terminais, ela é dita ε-livre.

Exemplo;

3.1.3. Produções Unitárias

Uma produção da forma A::= α em uma GLC = (N, T, P, S) é chamada de produção unitária se

α é um não terminal. Um caso especial de produção unitária é a produção A := A, também chamada

produção circular. Tal produção pode ser removida imediatamente sem afetar a capacidade da geração

da gramática. O algoritmo para eliminar produções unitárias assume que as produções circulares já

tenham sido eliminadas anteriormente.

Podem surgir símbolos inalcançáveis depois da aplicação do algoritmo. Isso se deve ao fato de

que o símbolo é substituído por suas produções, e se o mesmo aparecer somente em produções

unitárias, o mesmo irá desaparecer ao lado direito das produções. Para exemplificar, o algoritmo é

aplicado na seguinte gramática:

S ::= aB | aA | A B ::= aA | B | A

A ::= C | aaa C ::= ε | cBc

Primeiramente é necessário determinar o conjunto de Nk para cada não terminal K:

Ns = {S, A, B, C} Nb = {B, A, C} Na = {A, C} Nc = {C}

Page 31: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

31

As produções de cada símbolo K são as produções R ::= α, onde R é um elemento de Nk e α é

uma produção não unitária. No exemplo, as produções de S são as produções unitárias de S, A, B e C.

Exemplo;

Exercícios;

3.1.4. Eliminação de Recursão à Esquerda

Um não-terminal A, em uma GLC G=(N, T, P, S) é recursivo se A → αAβ, para α e β ∈ (N ∪

T)*.

Se α = ε, então A =e recursivo à esquerda; se β = ε, então A é recursivo à direita. Esta

recursividade pode ser indireta ou direta.

Uma gramática com pelo menos um não-terminal recursivo à esquerda ou à direita é uma

gramática recursiva à esquerda ou a direita, respectivamente.

Uma GLC G=(N, T, P, S) possui recursão à esquerda direta se P contém pelo menos uma

produção da forma A :: = Aα.

Uma GLC G=(N, T, P, S) possui recursão à esquerda indireta se existe em G uma derivação da

forma A →n Aβ, para algum n≥2.

Para eliminar recursão diretas à esquerda nas produções:

A ::= Aα1 | Aα2 | ... | Aαn | ... | β1 | β2 | ... | βm

Onde nenhum βi começa com A, deve-se substituir estas produções pelas seguintes:

A ::= β1A’ | β2A’ | ... | βmA’

A’ ::= α1A’ | α2A’| ... | αnA’ | ε

Onde A’ é um novo não-terminal.

Exemplo;

Exercícios;

3.1.5. Fatoração à Esquerda

A fatoração à esquerda é uma transformação útil para a criação de uma gramática adequada à

analise sintática preditiva. A idéia básica está em, quando não estiver claro qual das duas produções

alternativas usar para expandir um não-termimal A, estamos capacitados a reescrever as produções- A

e adiar a decisão até que tenhamos visto o suficiente da entrada para realizarmos a escolha certa.

Por exemplo, se tivermos as duas produções ao enxergarmos o token de entrada if, podemos

imediatamente dizer qual produção escolher a fim de expandir cmd. Em geral, se A → αβ1, αβ2 São

duas produções -A, e a entrada começa por uma cadeia não vazia derivada a partir de α, não sabe-se

Page 32: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

32

se vamos expandir A em αβ, ou αβ2. Entretanto, pode-se postergar a decisão expandido A para αA’.

Então, após enxergarmos a entrada derivada a partir de α, expandiremos A’ em β1 ou em β2. Isto é, as

produções originais, fatoradas à esquerda, tornam-se:

A → αA’

A’ → β1, β2

Entrada: Gramática G

Saída: Uma gramática equivalente fatorada à esquerda

Método: Para cada não-terminal A, encontrar o mais longo prefixo α comum a mais de duas ou mais

alternativas. Se α ≠ ∈, isto é, existe um prefixo comum não-trivial, substituir todas as produções de A,

A’ → αβ1 | αβ2 | ... | αβn | γ, onde γ representa todas as alternativas que não começam com α, por

A → αA’ | γ

A’ → β1 | β2 | ... | βn

Aqui, A’ é um novo não-terminal. Aplicar repetidamente esta transformação até que não haja

duas alternativas com um mesmo prefixo comum.

Exemplo;

Exercícios;

3.2. Conjuntos First e Follow

3.2.1. Conjunto First

Seja α uma forma sentencial qualquer gerada por G. FIRST(α) será o conjunto de símbolos

terminais que podem iniciar (que podem aparecer na posição mais à esquerda das sentenças

derivadas desta forma sentencial) α ou seqüências derivadas (direta ou indiretamente) de α. Além

disso, se α = ε ou α → ε então ε ∈ FIRST (α).

Para calcular FIRST(X) para todo X ∈ (N ∪ T)*, considera-se os seguintes aspectos especiais:

a) X = ε. Neste caso, FIRST(X) = {ε};

b) X ∈ T. Neste caso, FIRST(X) = {X};

c) X ∈ N. Neste caso, se X ::= α1 | α2 | ... | αn| são todas as produções com lado esquerdo X,

então FIRST(X) = FIRST(α1) ∪ FIRST(α2) ∪ ... ∪ FIRST(αn).

Page 33: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

33

Para determinar o conjunto FIRST de cada um dos não-terminais de uma gramática, procede-

se como:

1. Cria-se uma tabela TABFIRST cujas linhas são rotuladas com os não-terminais da

gramática e com uma coluna rotulada como “FIRST”, que irá conter os símbolos

pertencentes ao FIRST de cada não-terminal. Inicializa-se cada uma das posições desta

tabela com ∅ (conjunto vazio);

2. Para cada um dos não-terminais, calcula-se o seu conjunto FIRST;

3. Repete-se o passo 2 até que não ocorra mais nenhuma modificação na tabela;

Exemplo;

Exercícios;

3.2.2. Conjunto Follow

FOLLOW(A) é definido para todo A ∈ N como sendo o conjunto de símbolos terminais que

podem aparecer imediatamente após A em alguma forma sentencial de G. É definido um algoritmo que

constrói o FOLLOW de todo os não-terminais simultaneamente.

Duas observações importantes:

a) A função FIRST é definida para as cadeias de símbolos, FOLLOW só é definida para

não-terminais;

b) Os elementos de um conjunto FIRST pertencem ao conjunto T ∪∪∪∪ {εεεε}; os elementos

de um conjunto FOLLOW pertencem ao conjunto T ∪∪∪∪ {$}.

Exemplo;

Exercícios;

3.3. Autômatos com Pilha

Assim como as expressões regulares possuem seu Autômato equivalente – o Autômato Finito,

as gramáticas livres de contexto também possuem sua máquina equivalente – o Autômato com Pilha (‘

pushdown automata”). A equivalência é algo satisfatório desde que o autômato com pilha seja não

determinístico, pois sua versão determinística aceita somente os subconjuntos das linguagens livres de

contexto. Ou seja, nem toda linguagem livre de contexto pode ser reconhecida por um autômato com

pilha. Sendo assim, é necessário adicionar um aspecto que permita que ele reconheça qualquer

linguagem livre de contexto. Neste caso, uma pilha adicionada ao Autômato lhe confere a facilidade de

não-determinismo.

Page 34: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

34

O Autômato com Pilha é análogo ao Autômato Finito, incluindo uma pilha como memória

auxiliar. A pilha é independente da fita de entrada e não possui limite máximo de tamanho (memória

infinita). O A.P. é essencialmente um A.F. com controle da fita de entrada e da pilha.

Sua principal característica é que o último símbolo gravado é o primeiro a ser lido (“first in – last

out”), como mostra a figura abaixo:

Gravação Leitura

Topo

A base uma pilha é fixa e define o seu início.

O Autômato de Pilha é composta por quatro partes:

a) Fita: Análoga à do Autômato Finito;

b) Pilha: Memória auxiliar que pode ser usada livremente para leitura e gravação. É dividida

em células, armazenando cada uma,, um símbolo do alfabeto auxiliar (pode ser igual ao

alfabeto de entrada). Em uma estrutura do tipo pilha, a leitura ou gravação é sempre na

mesma extremidade denominada topo. O topo é variável e define a posição do último

símbolo gravado. Não possui tamanho fixo e nem máximo, sendo seu tamanho atual, igual

ao tamanho da palavra armazenada. Seu valor inicial é zero.

c) Unidade de Controle: Reflete o estado corrente da máquina. A unidade de controle possui

um número finito e pré-definido de estados. Possui uma cabeça de fita e uma cabeça de

pilha:

� Cabeça de Fita: unidade de leitura a qual acessa uma célula da fita de cada vez e

movimenta-se exclusivamente para a direita. É possível testar se a entrada foi

completamente lida.

� Cabeça da Pilha: unidade de leitura e gravação a qual move para a esquerda (ou “para

cima”) ao gravar e para direita (“ou para baixo”), ao ler um símbolo. Acessa um símbolo

Base

Sentido do Crescimento

Figura 2: Estrutura do Tipo Pilha.

Page 35: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

35

de cada vez, estando sempre posicionada no topo. A leitura exclui o símbolo lido. É

possível testar se a pilha está vazia. Em uma operação de gravação, é possível

armazenar uma palavra composta por mais de um símbolo. Neste caso, o símbolo do

topo é o mais à esquerda da palavra gravada.

d) Programa ou Função de Transição: Comanda a leitura da fita, leitura de gravação da pilha

e define o estado da máquina. É uma função parcial que dependendo do estado atual,

símbolo lido na fita e símbolo lido na pilha, determina o novo estado e a palavra a ser

gravada na pilha. Pode mudar de estado sem ler a fita (movimento vazio).

Um Autômato com Pilha Não-Determinístico (A.P.N) ou simplesmente Autômato com Pilha

(A.P) M é uma 6-upla:

M = (Σ, Q, δ, q0, F, V) onde:

Σ → alfabeto de entrada;

Q → conjunto de estados possíveis do autômato o qual é finito;

δ → função programa ou função de transição: δ : Q x (Σ ∪ {ε, ?}) x (V ∪ {ε, ?}) → 2QxV

q0 → estado inicial do autômato, tal que q0 é elemento de Q;

F → conjunto de estados finais tal que F ⊆ Q;

V → alfabeto auxiliar ou alfabeto da pilha.

Algumas considerações devem ser feitas em relação a função programa:

� O símbolo ε na. Ieitura indica que o A.P. não lê e nem move a cabeça da fita ou da pilha

(movimento vazio) e ε na gravação indica que nenhuma gravação é realizada na pilha (e

não move a cabeça);

� “?” significa que a função pode não ser total, ou seja, indefinida para alguns argumentos do

conjunto da partida. A omissão do parâmetro de leitura é denotada por “?”. Isto indica que

toda palavra de entrada foi lida na fita e na leitura faz o teste de pilha vazia.

3.3.1. Modelagem de MEF’s como SD’s

A modelagem de sistemas como autômatos não se limita ao estudo de reconhecimento de

linguagens formais. Muitos modelos têm sido propostos para resolução de vários problemas. Os

autômatos podem ser utilizados nas mais diversas aplicações, como por exemplo, modelos de redes

neurais artificiais e modelos de agentes, modelos de sistemas hipermídia. Aqui será restrito ao estudo

das linguagens formais.

Uma Máquina de Estados Finitos é um Sistema Dinâmico, onde o conjunto dos tempos é o

conjunto dos inteiros, e a entrada, a saída e os estados são conjuntos finitos. Neste caso, os valores

Page 36: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

36

possíveis de entrada e da saída são requeridos como alfabetos de entrada e saída. Sob estas

simplificações, basta declarar explicitamente um estado inicial correspondente ao tempo zero.

Um autômato (ou uma máquina) é descrito como uma 6-upla:

At = {U, Y, X, x0, λ, η}, onde:

U → é um conjunto finito de entradas;

Y → é um conjunto finito de saídas;

X → é um conjunto de estados ou espaço de estados;

x0 ∈ X é o estado inicial;

λ : U x X → é a função de próximo estado ou função de transição;

η : U x X → Y é a função de próxima saída.

Então um autômato é um sistema dinâmico invariante e discreto no tempo. Quando o espaço

de estado é um conjunto finito, o autômato é chamado de autômato finito.

Assim, esta sêxtupla formal pode ser interpretada como sendo uma descrição matemática de

uma máquina à qual, se no tempo t0, estiver no estado x0 e receber um segmento de entrada u do

tempo t0 ao tempo t estará no tempo t no estado λ(x, u) e emitirá a saída η(x, u).

Page 37: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

37

4. Teoria da Computação - Teoria de Problemas: Decidibilidade,

Computabilidade e Complexidade

4.1. Introdução

A Teoria da Computação pode ser vista como um guia (um roteiro) que nos orienta no sentido

de informar o que pode e o que não pode ser efetivamente computável, explicando porque, de que

forma e com que complexidade. Neste sentido, a Teoria da Computação classifica os problemas

computacionais em três classes:

a) Problemas Indecidíveis (ou impossíveis de serem solucionados);

b) Problemas Intratáveis (possíveis com recursos ilimitados, porém impossíveis com recursos

limitados);

c) Problemas Tratáveis (possíveis de serem solucionadas com recursos limitados).

Esta classificação engloba problemas de toda a natureza, envolvendo desde problemas clássicos

que fundamentam a teoria da computação até problemas (ou instâncias de problemas) práticos da

ciência da computação, tais como:

1 – Existe programa para solucionar um determinado problema?

2 – Qual o poder de expressão de um determinado modelo de especificação?

3 – Dado um programa qualquer, ele sempre tem parada garantida?

4 – Dois programas P1 e P2 são equivalentes entre si?

5 – Uma determinada solução é a melhor solução para um dado problema?

6 – Qual o significado de um determinado programa?

7 – Dado um programa qualquer, este programa está correto?

Esta lista poderia ser expandida e detalhada, contudo, seu objetivo é enfatizar a abrangência

da teoria da computação. Dos tópicos aqui listados, complexidade (5), semântica (6) e

correção/construção (7), costumam ser tratados como disciplinas específicas e independentes,

enquanto que os demais se classificam como problemas básicos da teoria da computação. Todos os

problemas computacionais podem ser tratados (estudados) sob a ótica da Teoria das Linguagens

Formais e Autômatos.

Page 38: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

38

Segundo esta ótica, a teoria da computação pode ser vista como um conjunto de modelos

formais (juntamente com suas propriedades) que fundamentam a ciência da computação. Tais modelos

incluem Autômatos (Finitos, de Pilha e Máquinas de Turing) e Gramáticas, enquanto que as

propriedades de interesse envolvem questões de decidibilidade, Inter-relacionamento entre modelos

(abrangência, equivalência, etc...) e complexidade computacional.

Nesta apostila, abordaremos a Teoria da Computação segundo a ótica da Teoria das

Linguagens Formais e Autômatos.

4.1.1. Conceitos e Propósitos Fundamentais da Teoria da Computação

Com o objetivo de melhor fundamentar as questões cobertas pela teoria da computação e de

identificar claramente a possibilidade de reduzir tais questões a problemas pertinentes a Teoria das

Linguagens Formais, apresentaremos nesta seção alguns conceitos fundamentais e comentamos

alguns dos principais propósitos que sustentam a teoria da computação.

Procedures e Algorítmos

O conceito de algoritmo é fundamental dentro da ciência da computação e pode ser definido

formalmente segundo vários propósitos da teoria da computação (como será visto no final desta seção)

ou informalmente em função da definição de procedure (como veremos a seguir).

Procedure: É m conjunto finito de passos (instruções), os quais podem ser executados mecanicamente

em uma quantidade fixa de tempo e com uma quantidade fixa de esforço. Um bom exemplo de uma

procedure é um programa de computador escrito em linguagem de máquina, pois tal programa possui

um número finito de passos, todos executáveis mecanicamente com uma quantidade fixa de recursos.

Algoritmo: É uma procedure que sempre pára; ou seja, uma procedure cuja execução chegará ao

final, independentemente de quais sejam suas entradas. Adicionalmente, dizemos que uma procedure

termina para uma determinada entrada, se existe um número finito t, tal que após a execução de t

instruções (não necessariamente distintas), ou não existem mais instruções a serem executadas, ou a

última instrução executada foi uma instrução “halt”.

Exemplos:

Page 39: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

39

1 – Dado um número inteiro positivo I, determinar se I é ou não um número primo.

2 – Dado um inteiro I, determinar se existe um número perfeito maior que I (obs: um número é perfeito

se a soma de seus divisores (exceto ele mesmo) é igual ao próprio número).

3 – Dado um programa escrito em uma determinada linguagem de programação, determinar se esse

programa está sintaticamente correto. Este problema é uma instância do seguinte problema genérico:

dada uma cadeia de caracteres x determinar se essa cadeia é gerada por uma Gramática Livre de

Contexto (ou reconhecida por um Autômato de Pilha).

4 – Dado um programa qualquer, determinar se existe alguma entrada para a qual o programa entrará

em loop.

Os problemas enunciados nos exemplos 1 e 3 possuem representação algorítmica enquanto

que os problemas dos exemplos 2 e 4 só são representáveis via procedures.

Conjuntos Recursivos e Conjuntos Recursivamente Enumeráveis

Um conjunto é dito Recursivamente Enumerável se ele pode ser representado (solucionado)

por uma procedure, e Recursivo se ele pode ser representado (solucionado) por um algoritmo. Como

procedures e algoritmos podem ser definidos formalmente através de vários modelos (gramáticas e

autômatos, por exemplo), podemos também definir conjuntos recursivos e recursivamente enumeráveis

em função de tais modelos.

Problemas Decidíveis e Indecidíveis X Algoritmos e Procedures

Um problema é decidível (tratável ou não) se e somente se ele é resolvível por um algoritmo,

para qualquer entrada pertencente ao seu domínio; caso contrário ele é um problema indecidível.

A partir das definições acima, podemos notar claramente a relação entre problemas decidíveis

e indecidíveis com conjuntos recursivos e recursivamente enumeráveis; ou seja, um problema é

decidível se o conjunto de soluções das diversas instâncias deste problema é um conjunto recursivo, e

indecidível caso tal conjunto seja recursivamente enumerável. Assim sendo, torna-se evidente que a

questão da decidibilidade pode ser tratada formalmente através dos modelos que compõem a Teoria

das Linguagens e Autômatos.

Page 40: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

40

A classe dos problemas indecidíveis é significativamente representada pelo “HALTING

PROBLEM” (problema da parada) que consiste em: “Dado uma procedure Z e uma entrada X, decidir

(determinar) se Z termina quando aplicado a X. A indecidibilidade deste problema é extremamente útil

para demonstrar a indecidibilidade de outros problemas através da redução destes para o ”halting

problem“.

Propósitos da Teoria da Computação

Até aqui definimos procedures e algoritmos de maneira intuitiva e informal. Contudo eles

podem ser definidos rigorosamente (precisamente) através de vários formalismos conhecidos como

propósitos (ou princípios) da Teoria da Computação. Tais formalismos tem sido explorados largamente

na Ciência da Computação, onde servem como modelos na solução de diversos problemas práticos.

Dentre os formalismos mais importantes, podemos citar:

a) Máquinas de Turing (Turing, 1936);

b) Gramáticas (Chomsky, 1959);

c) Algoritmos de Markov (Markov, 1951);

d) Lambda Calculus (Church, 1941);

e) Sistemas Post e Sistemas de Produção (Emil Post, 1936);

f) Funções Recursivas (Kleene, 1936).

Um ponto importante a ressaltar aqui, é que toda procedure (ou algoritmo) descrita por algum

destes formalismos, pode também ser descrita através de qualquer um dos demais; fato este que

sugere a equivalência entre os formalismos.

A aceitação destes formalismos dentro da teoria da computação é, em grande parte,

decorrente da hipótese (conhecida como Tese de Church) de que todo processo computável – passível

de ser descrito por uma procedure – pode ser realizado por uma Máquina de Turing. Esta tese, apesar

de não ter sido provada formalmente, também não foi contradita e continua sendo universalmente

aceita. Conseqüentemente podemos afirmar que Máquinas de Turing constituem o formalismo mais

genérico para a representação de procedure e que qualquer outro formalismo será significativo se for

considerado equivalente às máquinas de Turing. A demonstração formal da equivalência entre os

diversos formalismos citados e máquinas de Turing, reforça a tese de Church.

Page 41: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

41

4.2. Teoria de Problemas

Pode-se dizer que computadores servem para resolver problemas. A resolução de um

problema envolve o conhecimento do domínio do problema e a técnica de busca da solução. Caso o

conhecimento a cerca do problema for total não é necessário a utilização de técnica de busca da

solução, mas se não existir nenhum conhecimento a cerca do problema, ele é insolúvel. Então para a

solução de um problema devem ser considerado os seguintes aspectos:

� Conhecimento sobre o problema;

� Métodos de busca da solução;

Há uma autora que sugere antes de tentar buscar a solução de um problema tente responder

primeiro as seguintes questões:

� Quais são os dados?

� Quais são as soluções possíveis?

� O que caracteriza uma solução satisfatória?

4.2.1. Solucionabilidade de Problemas

O objetivo do estudo de problemas é investigar a existência ou não de algoritmos que

solucionem determinada classe de problemas.

Em particular, este estudo evita a pesquisa de algoritmos inexistentes. Em 1901, Hilbert

formulou uma lista de problemas a serem resolvidos pelas futuras gerações de matemáticos. Contudo,

o décimo problema desta lista (o desenvolvimento de um algoritmo que determine se uma equação

polinomial qualquer, com coeficientes inteiros, possui solução neste mesmo conjunto) foi aprovado, por

Matijasevic, em 1970, ser insolúvel.

4.2.2. Decidibilidade

Neste estudo, concentra-se nos problemas com respostas binárias sendo sim ou não, os quais

serão referidos simplesmente como problemas sim/não ou problemas de decisão.

Na prática, qualquer problema pode ser tratado equivalentemente como um problema (ou

classe de problema) sim/ não.

Os problemas solucionáveis são chamados computáveis. Alguns problemas não-solucionáveis

são parcialmente solucionáveis, ou seja, existe um algoritmo capaz de responder sim, embora,

eventualmente possa ficar em laço infinito para uma resposta que deveria ser não. Neste caso, diz-se

que o problema é parcialmente solucionável.

Page 42: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

42

4.2.3. Princípio da Resolução de Problemas

Pode-se afirmar que existem mais problemas não computáveis do que problemas computáveis.

O estudo da solucionabilidade de um problema é feito, em geral, usando o princípio da Redução. Este

princípio consiste em reduzir o problema que se está investigando a solucionabilidade em outro

problema que já se conheça que seja insolúvel. Desta forma implicaria em resolver o insolúvel. Sendo

assim, o princípio é resumido como segue:

a) Sendo A e B dois problemas de decisão. Suponha-se que seja possível modificar (reduzir)

o problema A de forma que ele se comporte como um caso do problema B.

b) Se A é insolúvel, não computável, e como A é um caso de B, conclui-se que B também é

não solucionável.

c) Se B é solucionável ( parcialmente computável), como A é um caso de B, conclui-se que A,

agora também seja solucionável.

4.2.4. Classes de Solucionabilidade de Problemas

De acordo com a possibilidade de estabelecimentos de algoritmos de solução, os problemas

podem ser agrupados nas seguintes classes:

� Problema Solucionável ou Totalmente Solucionável:

Um problema é tido como solucionável se existe algum algoritmo que resolva o problema,

sempre pára para qualquer que seja entrada, devolvendo uma resposta afirmativa (Aceita) ou

negativa(Rejeita).

� Problema Parcialmente Solucionável:

Um problema é Parcialmente Solucionável se existe um algoritmo que resolva o problema,

parando quando a resposta for afirmativa. No caso da resposta for negativa, o algoritmo pode parar ou

permanecer indefinidamente (LOOP). Ou seja, para qualquer algoritmo que processe esse problema,

existe pelo menos uma palavra de entrada que resulta em loop.

� Problema Não-Solucionável ou Insolúvel:

Quando não existe um algoritmo que resolva o problema tal que pára para qualquer entrada,

com uma resposta afirmativa ou negativa. Alguns problemas Não-Solucionáveis podem ser

Parcialmente Solucionáveis.

Page 43: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

43

A união dos conjuntos de problemas solucionáveis e não-solucionáveis é o universo de todos

os problemas. Entretanto, existem problemas parcialmente solucionáveis.

O conjunto dos problemas parcialmente solucionáveis contém todos os problemas

solucionáveis e alguns não-solucionáveis. Com isso, pode-se afirmar três coisas:

a) Todo problema solucionável é parcialmente solucionável;

b) Existem problemas não-solucionáveis que possuem solução parcial;

c) Existem problemas sem solução total ou parcial tido como insolúveis.

4.2.5. Definição Formal de Problema

Um problema é o objeto matemático P = {D, R, q}, consistindo de dois conjuntos não vazios,

dados (D) e possíveis resultados (R) e uma relação binária q ⊂ D x R como uma condição que

caracteriza uma solução satisfatória, associando a cada elemento do conjunto de dados a única

solução desejada.

A solução do problema é uma relação (subconjunto de um conjunto cartesiano) ou uma função

ƒ ( caso considerar os subconjuntos de dados), ver figura 2.1. Com isso, resolver um problema é

implementar funções através de mecanismos de implementações de funções.

Funções (ƒ) : ƒ1, ƒ2, ƒ3, ..., ƒn

Mecanismos de implementações (M): M1, M2, M3, ..., Mn

Dados Resultados

X X

ƒ

Figura 2: Demonstração de um problema como uma função.

Page 44: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

44

Denomina-se, então a solução de um problema como função.

ƒ : D → R ⇒ ∀d ∈ D

Tem-se: (d, ƒ(d)) ⊂ q

Sendo assim, um problema pode ser representado matematicamente por uma função.

Solucionar o problema, é encontrar uma maneira de implementar esta função ou de aproximá-la ao

conhecimento que dispõe.

Abaixo, apresenta-se um exemplo do autor Barreto.

- O conjunto de dados disponíveis d ∈ D, no qual d são dados (observação da amnese,

sintomas, resultados laboratoriais) que pertencem, ao conjunto D de dados disponíveis.

- R é o conjunto de doenças possíveis.

- A condição que caracteriza uma solução satisfatória consiste em encontrar o par (d, r),

onde r ∈ R é o diagnóstico desejado. Caso o diagnóstico for único, pode-se dizer que a

relação q torna-se uma função e, pode-se dizer que a solução do problema será poder

associar a cada elemento de D o elemento correspondente de R, de modo que (d, ƒ(d)) ∈

q (onde ƒ(d) = r) e ƒ é uma função.

Formular um problema é diferente de encontrar a solução. A definição de um problema

possibilita testar se um determinado elemento é ou não a solução, mas não auxilia na busca deste

elemento. Verificar se um elemento é a solução, verifica-se se o par (dado, elemento e candidato à

solução) satisfaz ou não a condição. Testar se um par (dado, elemento e candidato à solução) satisfaz

a solução de um problema, nem sempre é permitido. Isto depende do modo de definir a função

associada ao problema em questão.

X X

Dados Resultados

ƒ

f1 f2 f3 fn

ƒ

Figura 3: Resolução do problema: implementações de funções.

Page 45: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

45

4.2.6. Modos de Definir uma Função

� Por enumeração exaustiva:

Neste método, fornece-se todos os conjuntos de pares, dados, resultado. Só é aplicado no

caso do conjunto de dados ser finito.

Exemplo: Numa agenda de telefones pode ser considerada como uma função que associa a

cada nome de pessoa seu telefone. Calcular o valor da função é simples e sempre possível, neste

caso, se o nome da pessoa pertencer ao conjunto de dados representado na agenda. Saber se um par

(nome, número de telefone) está na agenda também é fácil e sempre possível: basta olhar na agenda.

� Declarativa:

Definir um problema desta maneira é atribuir propriedades que devem ser satisfeitas pela

solução do problema. Da mesma forma que um conjunto pode ser definido por uma propriedade (ex:

conjunto dos objetos de madeira de uma sala), uma função pode ser definida por uma propriedade.

Exemplo: Seja a propriedade de pertencer a um conjunto. Neste caso, trata-se da definição da

função característica de um conjunto.

Normalmente costuma-se considerar o conceito de um elemento pertencer a um conjunto como

conceito primitivo, explicado, mas não definido. Entretanto, este, conceito pode ser substituído pelo de

uma função característica de um conjunto. Pertencer passará a ser um conceito definido e a função

característica do conjunto A será:

FA : U → Verdadeiro, Falso,

significa que se a imagem do elemento for Verdade, ele pertence ao conjunto e Falso se não pertencer.

� Por um Programa:

Um programa de computador define a correspondência entre dados e resultados sempre ele

conseguir chegar a uma solução. Portanto, um programa pode ser considerado como um modo de

definir um problema.

Exemplo: Neste modo, o problema não é completamente definido para todo valor de seus

dados. Conhece-se apenas a definição do problema para um subconjunto dos dados possíveis e este

conhecimento pode ser de qualquer uma das formas citadas: por enumeração, declarativamente ou

proceduralmente. Deseja-se conhecer os elementos do conjunto de respostas admissíveis para todos

os elementos do conjunto de dados, mesmo aquele que não estão incluídos na definição da função.

Pode-se reconhecer neste caso que a solução não é única: todas as funções que sejam iguais

dentro da região em que o problema é definido são válidas. Também, deve-se considerar que, neste

Page 46: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

46

caso, muitas vezes, é melhor Ter uma solução aproximada quando dados são usados para definir a

função.

As maneiras de definir uma função levam ao conceito de computabilidade.

4.3. Computabilidade

Uma função é computável se for possível calcular seu valor para todos os elementos do seu

domínio de definição. Caso contrário é considerada não computável.

Uma função também pode ser considerada parcialmente computável se for possível calcular

seu valor para alguns elementos, pelo menos, de seu domínio de definição.

4.3.1. Origem da Computabilidade

A idéia de Ter um algoritmo, ou passos para desenvolver uma determinada tarefa, existe por

muitos anos.

Durante anos, acreditava-se que: se um determinado problema fosse precisamente declarado,

com esforço suficiente, uma solução poderia eventualmente ser encontrada ( ou senão, poderia ser

provado que não havia solução). Ou seja, acredita-se que nenhum problema era intrinsecamente difícil,

em princípio, que jamais poderia ser resolvido.

Um dos grandes percursores desta idéia foi o matemático David Hilbert (1862 – 1943). Hilbert

acreditava que todos os problemas poderiam ser precisamente formulados, num sistema formal, em

termos de declarações que poderiam ser falas ou verdadeiras. Sua idéia era encontrar um algoritmo

que, dado um sistema formal, poderia determinar se a declaração a cerca do problema era ou não

verdadeira. Se o objetivo de Hilbert fosse atingido, então qualquer problema bem definido (declarado

com precisão) poderia ser resolvido simplesmente pela execução de um algoritmo. A decisão da

verdade sobre uma determinada declaração em um sistema formal ficou conhecida como

Entscheidungsproblem. Este problema pode ser considerado o problema aberto fundamental da

matemática.

Mas, infelizmente, na década de 30, muitas pesquisas constataram que o

Entscheidungsproblem é não computável, não existia nenhum algoritmo do tipo sugerido por Hilbert.

� Teorema de Gödel

Uma das primeiras descobertas nesta linha, deve-se a Kurt Gödel, que em 1931 sugeriu um

Teorema da Não-Completude. (“Incopleteness Theorem”). Entre outras coisas, ele mostrou que não

Page 47: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

47

existe algoritmo cujas entradas declaradas sejam números inteiros e cuja saída mostre se esta

declaração é verdadeira ou não.

No Teorema da Não-Completude (ou Incompleteza) de Gödel, um sistema de axiomas é dito

completo quando todo teorema é verdade ou mentira. Se existir um sistema de axiomas consistentes

(quando não existirem axiomas que entrem em contradição com outros axiomas) existirão sempre

teoremas que poderá provar que são mentiras e teoremas que poderão provar que são verdades.

Outros também que não podem provar nada, nem que sejam verdades, nem que sejam mentiras.

Neste caso, o sistema é dado como incompleto, no sentido de que existem coisas que não pode-se

provar, nem verdades, nem mentiras.

Este teorema parte da premissa de que existem verdades e mentiras levando a conclusão que

existem teoremas verdadeiros, falsos e outros que não sabem se são verdades ou mentiras.

Alguns outros matemáticos como Alonso Church, Stephen Kleene, Emil Post, Alan Turing

encontraram vários problemas que não possuem solução algorítmica.

� A Tese de Church – Turing

Um dos maiores obstáculos em saber se existe ou não algoritmo para resolver um determinado

problema é saber exatamente o significado de algoritmo.

Gödel definiu algoritmo como uma seqüência de regras para transformar funções matemáticas

complexas em funções matemáticas simples.

Church utilizou um formalismo chamado cálculo lambda.

Turing imaginou uma máquina hipotética (Máquina de Turing) definindo um algoritmo como

sendo qualquer conjunto de instruções para esta máquina.

Um algoritmo também pode ser definido como operações básicas em estruturas de dados

controladas por seqüência, seleção e iteração.

Uma conjectura, enunciada por Church, diz que todos os modelos razoáveis do processo de

computação, definidos e por definir, são equivalentes. Essa conjectura é conhecida como a Tese de

Church. A Tese de Church não admite nenhuma prova formal, mas até hoje todos os modelos

propostos se manteram equivalentes. Com conclusões:

� Todas estas definições de “algoritmo” são equivalentes;

� Qualquer definição razoável de algoritmo será equivalente a estas definições;

A tese de Church-Turing ( ou Tese de Church), define que se tem uma boa definição de algoritmo

se uma seqüência de passos possa ser executada de maneira rotineira (ou mecânica), de maneira

formal no desenvolvimento da mesma tarefa.

Page 48: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

48

� Procedimento e Algoritmo

Um procedimento é definido como “uma seqüência finita de instruções, e define-se uma

instrução como uma operação claramente descrita, que pode ser executada mecanicamente, em tempo

finito”.

� “mecanicamente” significa que deve haver dúvidas sobre o que deve ser feito;

� “em tempo finito” significa que não há dúvidas de que a tarefa correspondente à

instrução pode, em qualquer caso, ser conduzida até sua conclusão.

Para se escrever um procedimento pode-se usar uma linguagem natural, uma linguagem de

programação, ou uma linguagem usada em matemática.

Na verdade, usa-se uma combinação de todas elas. Sobre a forma de escrever instruções e

procedimentos, supõe-se apenas que existe uma linguagem, comum a todos, em que instruções e

procedimentos podem ser escritos sem ambigüidade.

Exemplos:

� o algoritmo Euclides para cálculo máximo divisor comum de dois números naturais;

� um programa em PASCAL que calcula a soma de dois números;

� a fórmula de Bháscara que calcula as raízes da equação de segundo grau.

Por exemplo, um conjunto A é recursivamente enumerável se existe um procedimento que

enumera os elementos de A Existe então um procedimento que emite todos os elementos de A,

possivelmente com repetições.

Define-se então algoritmo como sendo um procedimento que sempre pára, quaisquer que

sejam os valores de suas entradas. Por exemplo, conjunto A é dito recursivo se existe um algoritmo

que determina para um valor arbitrário de sua entrada x, se x ∈ A ou se x A. Embora isso não seja

estritamente necessário, pode-se, para fixar as idéias, especificar que o algoritmo deve parar e dizer

“sim” ou “não”, respondendo a pergunte, se “x ∈ A”?.

No sentido moderno, pode-se definir um algoritmo como sendo qualquer coisa que possa ser

executada no computador. O computador particular escolhido é irrelevante para a definição, desde que

qualquer algoritmo que possa ser implementado em um computador possa ser implementado em outro.

Isto é real, porque todos os computadores podem simular um ao outro. Este programa é conhecido

como interpretador (ou simulador, ou programa universal).

A equivalência entre todos os computadores modernos, e sua equivalência às Máquinas de

Turing e outras definição de “algoritmo evidenciam a Tese de Church. A universalidade é uma

propriedade dos algoritmos, significando que qualquer computador é equivalente a todos os outros no

sentido de que todos eles podem desenvolver a mesma tarefa. Embora os computadores possam

Page 49: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

49

desenvolver as mesmas tarefas, eles não necessariamente consomem os mesmos recursos

computacionais.

4.3.2. Computabilidade de Funções

� Funções Computáveis:

Um problema de Decisão é o processo de determinação, se um determinado elemento é ou

não membro de um conjunto. È altamente desejável saber antecipadamente se um determinado

problema de decisão pode ser ou não resolvido pelo computador (ser computável). De modo teórico,

pode-se dizer que um problema é computável se a função característica do conjunto for recursiva. De

modo prático, uma função é dita computável se para qualquer entrada de dados pode ser

implementada no computador em tempo finito, ou seja, o programa irá parar para qualquer entrada de

dados. A maioria das linguagens de programação oferecem algumas funções intrínsecas e também

permitem aos programadores definir novas funções.

Exemplo:

Se desejar usar uma função que computa a média entre valores de três números reais pode-se

utilizar o seguinte código em PASCAL. O qual permite definir tal função:

function media(x, y, z: real):real;

{encontra a média dos valores de três números reais}

begin (função média}

media := (x + y + z) / 3.0;

end;

O cabeçalho function dentro dos parênteses indica que a função consiste de todas 3-tuplas de

números reais. Para cada uma delas é esperado que a função produza um resultado único.

� Funções Parcialmente Computáveis:

Na computação, algumas funções não são definidas para algumas entradas. Teoricamente é

impossível, dado um programa sem conhecer sua estrutura interna garantir que ele termine com certo

tipo de entrada. Pode acontecer de escolher um conjunto de dados de entrada e se o programa tiver

laços pode entrar num loop infinito e nunca parar. Com isso, os programas podem gerar funções

parcialmente computáveis.

Exemplo:

Page 50: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

50

function ƒ (x:integer): integer;

var

y:integer;

begin

y := 1;

while (x<>0) do

begin

x := x – 2;

y := y * 2;

end;

ƒ := y;

end;

Percebe-se que a chamada ƒ (2K), com K ≥ 0 retorna o número 2K. Para qualquer outra

entrada, o programa não pára. Portanto, este fragmento de programa computa a função F = {(2K, 2K ) |

K ∈ N}, a qual é uma função parcial de Z em Z.

� Funções Não Computáveis:

As funções não computáveis são aquelas que não podem ser implementadas no computador.

Pode-se considerar como funções não computáveis àquelas cujo tempo de execução do programa não

é hábil, quer dizer, o computador pode levar muito tempo para implementar tais funções.

Exemplo:

Dada uma equação arbitrária da forma (a + 1)2 + (b + 1)3 = (c + 1)4, o problema é determinar se

a equação é satisfeita por quaisquer números inteiros. Isto é chamado Problema da Equação

Diofantinas e sabe-se que não existe algoritmo de solução de equações Diofantinas Arbitrárias.

4.3.3. Problema da Parada

Vários problemas são conhecidos como não computáveis, ou seja, não são conhecidos

algoritmos para a resolução de tais problemas. Estes algoritmos não conhecidos porque simplesmente

não existem!

Um problema comum nos sistemas computacionais é a ocorrência de erros que impedem a

determinação normal do programa. Várias vezes, os problemas sem detectar a existência de laços

infinitos em seus programas antes de dispensar recursos computacionais na execução dos mesmos.

Page 51: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

51

Portanto, o problema a ser resolvido é determinar se um programa arbitrário (qualquer) pára ou não

pára. Este é denominado “Problema de Parada”. Sua solução é um algoritmo, no qual, dado um

programa qualquer P e sua entrada de dados D, pode-se dizer ou não, se eventualmente P pára

quando executado com a entrada de dados D.

Muitas vezes a “solução” para o Problema da Parada, utilizado em muitos sistemas

computacionais, é forçar a parada do programa cada vez que sua execução ultrapasse o tempo

determinado (alocado) para isso. Mas esta solução não é adequada por duas razões:

� Os programas não terminantes pode alocar todo tempo dispensado na execução;

� Nem sempre o programa pode calcular o tempo necessário para a execução do programa,

e ele pode “terminar” de maneira precoce em um tempo inferior à sua parada com sucesso.

O Problema da Parada é não computável conforme a seguir:

Suponha que exista um algoritmo para resolver o Problema da Parada, testaparada. O

algoritmo testaparada possui duas entradas, P e D. Imprime a resposta “OK!” caso o programa P

termina quando é executada com uma entrada de dados D. E imprime “Não Pára!” caso contrário.

O testaparada testa a determinação do programa P para dados D conforme mostra a figura

abaixo:

P(D) pára?

Saída “OK!” Saída “Não Pára”

e pára e pára

Suponha-se que pode-se usá-la para construir um algoritmo mais limitado, o qual testa a

terminação de P quando os dados são o próprio P, o qual será chamado de novotestaparada.

Embora posa parecer estranho a entrada de dados com o próprio programa, sabe-se qualquer

seqüência de caracteres pode ser a entrada de um programa. Assim, existem programas de interesses

prático, cuja a entrada é uma seqüência de caracteres representando outro programa; exemplos são

compiladores e editores.

Figura 4: Ação Testaparada.

P D

Page 52: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

52

Programa novotestaparada(P)

{ verifica se o programa P pára quando é executado com o dado sendo o próprio P }

testaparada(P,P)

A ação de novotestaparada é demonstrado na figura 2.4.

P

P(P) pára?

Saída “OK!” Saída “Não Pára”

e pára e pára

Supondo a existência do algoritmo testaparada estar-se-á supondo a existência também de

novotestaparada. Assim, pode-se construir o seguinte algoritmo, chamado parada, que possui apenas

uma entrada P.

Programa parada(P)

{para escrever esta rotina suponha-se que testaparada existe}

Se novotestaparada(P) sai “Não Pára!”

então pára

senão laço infinito

A demonstração do algoritmo parada está na figura 2.5.

Sim Não

Figura 5: Ação de novotestaparada.

Page 53: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

53

P

P(P) Pára?

Pára

Laço Infinito

Finalmente, considerando o que ocorre durante a execução de parada(parada), ou seja,

durante a execução de parda com sua própria entrada de dados, um programa texto de P (P pode ser

qualquer seqüência de caracteres). A execução de parada(parada) é demonstrada na figura 2.6. Sendo

a mesma figura 2.5, mas a entrada P foi substituída pelo próprio parada.

parada

parada(parada) pára?

Sim Não

pára

laço infinito

A figura 2.6 mostra uma contradição, pois se a parada (parada) pára então ele entra em laço

infinito. Por outro lado, se parada(parada) entra em laço infinito então ele pára! Ou seja, a execução de

parada(parada) não pode parar nem entrar em laço infinito.

Esta contradição só pode ser resolvida admitindo-se que o algoritmo parada não existe. Porém,

a única suposição feita derivando parada, era que testaparada não existiria. Portanto, se parada não

Sim Não

Figura 6: Ação de parada(P).

Figura 2.6: Ação de parada(parada).

Page 54: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

54

existe, então testaparada não existe. Concluindo com isso, que não existe algoritmo que solucione o

problema da parada (testaparada). Assim, o problema da Parada é não computável!

Resumindo:

1. Suponha-se que pode-se escrever o programa testaparada;

2. Usa-se este programa para construir outro programa (parada) através de um programa

intermediário (novotestaparada);

3. Mostra-se que parada tem algumas propriedades impossíveis (não pode parar e nem

entrar em laço infinito);

4. Conclui-se que a suposição no passo 1 está errada.

4.3.4. Exemplo Problemas Não Computáveis

É possível projetar um algoritmo o qual resolverá o problema da Parada em alguns casos. Mas

o algoritmo é limitado e pode falhar com outras entradas. Ë difícil determinar se um dado algoritmo

falha e quando (momento em que) ele falha.

Pode-se dizer que o Problema da Parada não pode ser resolvido por qualquer programa,

escrito em qualquer linguagem, para qualquer computador!

� Problema da Totalidade:

Sendo que o Problema da Parada é determinar se um programa arbitrário P pára ou não pára

quando executando com uma entrada de dados arbitrária D. A questão é saber se o programa arbitrário

P parará para todas as entradas. Este é denominado “Problema da Totalidade”. Assim, pode-se dizer

que P é total se P(D) pára para qualquer entrada de dados D.

É de se esperar que o Problema da Totalidade seja não computável. Ao contrário, dado

qualquer P e D, pode-se simplesmente construir um programa especial afim de que P e D ignorar sua

entrada e simular P(D). Este programa especial pode ser denominado paradapd.

Programa paradapd(E)

{é a entrada mas o programa não usará, ele apenas simula uma entrada de dados D}

simular o programa P com a entrada de dados D

Agora, perguntar se paradapd é total é o mesmo que perguntar se P(D) pára. Então, um

algoritmo para o Problema da Totalidade poderia também ser dado para o Problema da Parada:

Page 55: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

55

Programa testaparada(P,D)

{para escrever este programa supõe-se que o algoritmo para o Problema da Totalidade

existe}

construir a entrada do programa paradapd

se paradapd é total

então imprimir “OK” e pára

senão imprimir “Não Pára” e pára

4.3.5. Computabilidade Parcial

Existem muitos problemas os quais não são computáveis. Todavia, alguns destes problemas

não computáveis são menos computáveis do que outro. Mas aqui terão mais atenção problemas que

requerem uma resposta “sim” ou “não”.

Considera-se novamente o Problema da Parada. Para um programa arbitrário P e sua entrada

de dados D, deseja-se saber se P(D) pára ou não. Se P(D) pára, não existe dificuldade porque pode-se

simplesmente executar este programa até que ele pare pois sabe-se que ele pára. A dificuldade

aparece no caso de P(D) não pára. Portanto, não existe um método geral (algoritmo) que possa

descobrir se P(D) não pára.

O Problema da Parada também é denominado “parcialmente computável” porque existe um

algoritmo que imprime sim”” se P(D) pára e outro que entram laço infinito se P(D) não pára. A diferença

entre a computabilidade e a computabilidade parcial é demonstrada na figura 2.7.

Entrada Entrada

Sim Não Sim Não

Algoritmo Algoritmo

Figura 7: Computabilidade Parcial.

Page 56: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

56

Ao contrário do Problema da Parada, o Problema da Totalidade por exemplo, não são

parcialmente computáveis. Para este problema não existe algoritmo que imprima “Sim” se P pára para

todas entradas de dados e também permita entrar em laço infinito quando a resposta é “Não”.

4.3.6. Complexidade

O estudo da Computabilidade leva ao entendimento de quais problemas admitem solução

algorítmica ou não. Para aqueles problemas que existem algoritmos é válido saber quais os recursos

computacionais são necessários para a sua execução. Somente aqueles algoritmos que podem utilizar

uma quantia de recursos viáveis são de interesse prático. Isto é um campo da ciência da computação

denominado Teoria da Complexidade.

A figura 2.8 demonstra uma representação do universo de problemas. Aqueles que podem ser

computados algoritmicamente forma um pequeno subconjunto. Aqueles viavelmente computáveis, de

acordo com recursos que necessitam compreendem uma pequena porção deste subconjunto

infinitesimal.

4.3.7. Recursos Computacionais

Os maiores recursos computacionais de interesse são tempo, memória e hardware. O tempo é

o período necessário para o início e o término da execução de um algoritmo.

A memória é a quantia de armazenamento requerida pelo algoritmo. O hardware é a

quantidade de mecanismos físicos necessários para a execução de um algoritmo. Em uma máquina

Todos Problemas

Problemas Computáveis

Problemas viavelmente Computáveis

Figura 8: Universo de Problemas.

Page 57: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

57

paralela, por exemplo, o hardware está intimamente ligado ao número de processadores necessários

pelo algoritmo.

Os algoritmos usualmente aceitam dados de entrada conforme seu processamento. Portanto, a

quantia de qualquer recurso usado pelo algoritmo pode variar de acordo com o tamanho dos dados.

Considera-se, por exemplo, um algoritmo que multiplica dois números. A figura 2.9 mostra um algoritmo

feito no “jardim de infância”. Se o algoritmo é apresentado com dois n-dígitos, necessita-se adicionar n

linhas, cada uma contendo n( ou n+1) dígitos. Cada linha pode ser computada com cerca de n passos,

ou n unidades de tempo, e existirá n linhas separadas. Adiciona as linhas é tomar n x n (ou n2)

unidades de tempo. Portanto, o tempo de execução deste algoritmo é proporcional a n2.

Existem outras formas de algoritmos de multiplicação, algumas bem mais rápidas que podem

ser feitas em computadores paralelos, mas problema é encontrar aqueles que têm a execução mais

rápida e demanda menos recursos computacionais.

A quantidade de recursos usados depende do tamanho dos dados de entrada. Assim, no caso

da multiplicação, quanto mais número a serem multiplicados mais tempo será necessário para

desenvolver esta multiplicação.

A teoria da Complexidade estuda vários recursos computacionais. A quantidade de recursos

usados por um algoritmo é expressa como uma função do tamanho dos dados de entrada.

Os algoritmos podem utilizar diferentes entrada de mesmo tamanho. É importante conhecer a

quantia de recursos usados pelo algoritmo para qualquer entrada de um dado tamanho. Por exemplo,

se o computador está controlando um reator nuclear ou lançando um foguete, é vital saber o tempo

mais longo necessário ao computador para responder a uma situação de emergência. Isto é

denominado complexidade no pior caso do algoritmo.

Alternativamente, conhecer a quantia média de recursos usados para todas as entradas de um

dado tamanho pode ser bastante útil. Isto é denominado complexidade média. Às vezes, é interessante

conhecer a chance do algoritmo permanecer perto de seu comportamento médio para um dado de

entrada. Neste caso, o desvio padrão do recurso utilizado, poderia ser calculado.

Várias vezes se conhecem os limites (inferior e superior) que se aproximam na solução de

determinado problema. A complexidade de algoritmos envolve a complexidade de problemas em

relação aos recursos necessários para resolver determinado problema. Isto é a complexidade de um

problema, é a complexidade do melhor algoritmo, o qual resolve este problema. A análise do algoritmo

fornece um limite superior (“upper bound”) para a quantidade de recursos que é suficiente para resolver

um problema. Para saber quanto pode-se melhorar este algoritmo, precisa-se estabelecer um limite

inferior (“lower bound”) na quantidade de recursos necessários, ou seja, qual a quantidade mínima

Page 58: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

58

necessária de recursos para a solução do problema. Naturalmente, tem-se interesse em estabelecer o

mais limite e, analogamente, o menor limite superior possível.

Idealmente, os dois limites, inferior e superior, deveriam ser iguais, pois neste caso, saberia

exatamente a quantidade de recursos que é tanto necessária quanto suficiente para resolver um

problema.

Se utilizar um algoritmo que utilize exatamente esta quantidade de recursos, então, tem-se um

algoritmo ótimo para a tarefa.

A diferença entre limite inferior e superior demonstra uma medida de quanto o algoritmo pode

ser melhorado. Nem sempre é possível construir algoritmos ótimos.

A fim de capturar a noção de algoritmo praticamente viável, deve-se limitar os dispositivos

computacionais para somente executar um número de passos que é limitado por um polinômio no

comprimento da entrada. A esta classe de problemas denomina-se classe P. Existem problemas que

possuem verificação algorítmica em tempo não polinomial e formam a classe NP. Mas existem

problemas que não possuem uma fácil verificação algorítmica, os quais são denominados de

problemas “NP-Completos”. O tempo de execução destes algoritmos é não polinomial e de difícil

verificação. Os problemas de decisão na classe NP permitem que validem potenciais soluções em um

tempo polinomial. Isso quer dizer que para problemas NP utiliza-se uma redutibilidade polinomial.

4.3.8. Problemas Tratáveis e Intratáveis

Considerando a coleção de todos os algoritmos que resolvem certo problema P. Se existir um

algoritmo de complexidade polinomial, então P é denominado tratável; caso contrário é denominado

intratável. A idéia é que um problema tratável sempre pode ser resolvido por um processo automático

(computador, por ex.) em, tempo factível. Algoritmos não polinomiais, de problema intratável, podem

levar séculos, mesmo para entradas de tamanho reduzido.

Da Teoria da Complexidade pode-se considerar alguns critérios práticos para o julgamento de

um programa:

� Ele faz exatamente o que espera que faça?

� Ele o faz corretamente, de acordo com as especificações originais da tarefa?

� Há uma documentação que descreva como usá-lo e como ele trabalha?

� As sub-rotinas são criadas de tal modo que realizem sub-funções lógicas?

� O código é legível?

� Ele é executado em tempo ótimo de execução?

� Ele utiliza memória mínima necessária para sua execução?

Page 59: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

59

Com essas considerações conclui-se que:

� Um algoritmo é eficiente precisamente quando sua complexidade for baixa;

� Um algoritmo é eficiente precisamente quando a sua complexidade for um polinômio nos

tamanhos de entrada e saída;

� Este critério não é absoluto, mas na maioria os casos é realmente aceitável.

4.3.9. Modelo Formal de Algoritmo: Máquina de Turing

Para se estudar os limites da computabilidade e da complexidade computacional, é necessário

escolher um modelo formal de algoritmo. O mais utilizado é o da Máquina de Turing, pois:

� É suficientemente simples, facilitando demonstrações, e,

� Ao mesmo tempo, é suficientemente poderoso para que os resultados se apliquem a

� Modelos aparentemente com mais recursos (na verdade, poderoso o suficiente para que

qualquer algoritmo possa ser nele representado).

Em 1936 o matemático britânico Alan Turing imaginou uma máquina abstrata denominada

Turing Machine. A Máquina de Turing será estudada melhor mais adiante.

Page 60: Apostila LFA.pdf

UEMS - Professora Viviane Duarte Bonfim

60

REFERÊNCIAS BIBLIOGRÁFICAS

Apostila de Teoria dos Autômatos e da Computabilidade. Professora Maria Aparecida Fernandes de

Almeida. Agosto, 2001.

Apostila de Linguagens Formais e Compiladores. Professor Olinto José Varela Furtado, Universidade

Federal de Santa Catarina – UFSC, 2003.

Apostila de Compiladores. Professor Bráulio Adriano de Mello. Agosto, 2001.

ARBIB, M. A Theories of Abstract Automata. Prentice Hall in Automatic Computation, 1969.

DIVÉRIO, TIARAJU ASMUZ & MENEZES, Paulo F. Bath. Teoria da Computação, Série de Livros

Didáticos, Porto Alegre: Editora Sagra Luzzato.

DOMÊNICO, L. C. Matemática 3 em 1, Curso Completo de 2º Grau. São Paulo: Instituto Brasileiro de

Edições Pedagógicas.

GIOVANI, J. R. & BONJORNO, J. R. Matemática, 2º Grau, Vol. 1. São Paulo: Editora FTDS.A.

HOPCROFT, J. E., ULLMAN, J. D. Introduction to Automata Theory, Languages and Computation. New

York : Addison Wesley, 1979.

Material sobre Grafos. Disponível em http://www.ulbra.tche.br/~danielnm/ed/B/polB.html. Fevereiro,

2001.

MENEZES, P. F. B. Linguagens Formais e Autômatos. 4º ed. Série de Livros Didáticos. Porto Alegre :

Sagra Luzzato, 2001.