PCS 2427 – Lógica Computacional – Prof. João José Neto – Aula 1 Assunto: Conceitos. Teoria de Linguagens. Hierarquia de Chomsky. a)Conceitos Alfabetos são conjuntos finitos e não-vazios de símbolos Uma cadeia sobre um alfabeto é uma seqüência finita de símbolos do alfabeto A cadeia vazia não contém símbolos S* é o conjunto de todas as cadeia possíveis (incluindo a cadeia vazia ) sobre o alfabeto S Comprimento de uma cadeia é o número de símbolos da seqüência que a compõe Um mesmo símbolo s pode ocorrer mais de uma vez na mesma cadeia Concatenação w=xy de duas cadeias x e y é a cadeia formada pela justaposição de x com y A concatenação é associativa, não-comutativa e seu elemento neutro é a cadeia vazia. Uma cadeia v é sub-cadeia de outra cadeia w se e somente se existirem x e y tais que w=xvy. Nesse caso, Se w = xv, v é sufixo de w, e se w = vy, v é prefixo de w Para cada natural i e cada cadeia w define-se: w0=; wi+1=wwi Define-se cadeia reversa wR de uma cadeia w: Se w = , então wR = w = . Se |w| = n+1 > 0, e w=ua para aS, então wR=auR Um conjunto de cadeias sobre S (um subconjunto de S*) é chamado linguagem. Linguagens infinitas são conjuntos do tipo L={ wS* | w tem a propriedade P} Se S é finito, S* será o conjunto de todas as possíveis cadeias de símbolos de S Pode-se definir para linguagens L, L’: Complemento de uma linguagem S*-L Concatenação de linguagens LL’ Fechamento reflexivo e transitivo de uma linguagem L* Fechamento transitivo da linguagem L L+=LL* b) Representação finita de linguagens Representações de linguagens são cadeias finitas sobre um alfabeto finito Logo existe un número infinito, enumerável, de representações para linguagens Algumas representações usuais de linguagens: expressões regulares, para linguagens regulares; geradores ou gramáticas; reconhecedores ou autômatos; algoritmos c) Terminologia básica ÁTOMO - elemento básico da linguagem ALFABETO - conjunto de átomos CADEIA - concatenação arbitrária de símbolos do alfabeto SENTENÇA - cadeia pertencente à linguagem LINGUAGEM - conjunto de todas as sentenças válidas GRAMÁTICA - enumeração ou conjunto de leis de formação DERIVAÇÃO - obtenção de sentenças usando gramáticas RECONHECEDORES - conjunto de regras de aceitação RECONHECIMENTO - aceitação das sentenças da linguagem ALFABETO - conjunto finito não-vazio de átomos CADEIA VAZIA - seqüência de zero átomos CADEIA ELEMENTAR - seqüência de um só átomo COMPRIMENTO - número de átomos de uma cadeia CONCATENAÇÃO DE CADEIAS - obtida por justaposição das cadeias CONCATENAÇÃO DE CADEIA COM ÁTOMO = com cadeia elementar d) Hierarquia de Chomsky
Tipo 0 - Gramáticas irrestritas - geram linguagens estruturadas em frases Tipo 1 - Gramáticas sensíveis ao contexto - geram linguagens sensíveis ao contexto Tipo 2 - Gramáticas livres de contexto - geram linguagens livres de contexto Tipo 3 - Gramáticas lineares - geram linguagens regulares Gramática Reconhecedor Linguagem irrestrita máq. de turing c/ fita conjuntos recursivamente Tipo 0 infinita enumeráveis dependente de contexto máq. de turing c/ fita ling. dependentes de contexto Tipo 1 limitada livre de contexto autômato de pilha ling. livres de contexto Tipo 2 linear autômato finito linguagens regulares Tipo 3 e) Propriedades da concatenação de cadeias ASSOCIATIVA; NÃO-COMUTATIVA; ELEMENTO NEUTRO É A CADEIA VAZIA f) Fechamentos TRANSITIVO - conjunto de todas as cadeias não-vazias REFLEXIVO E TRANSITIVO - inclui a cadeia vazia Os fechamentos podem ser aplicados a operadores, indicando sua repetida aplicação g) Gramáticas - são dispositivos de geração de sentenças Componentes: vocabulário da gramática (terminais e não-terminais); terminais da gramática (átomos da linguagem); símbolo inicial ou raiz da gramática (não-terminal); produções da gramática (regras de substituição). Derivação direta é a operação resultante da aplicação de uma produção apenas Forma sentencial é qualquer cadeia sobre o vocabulário, derivável a partir da raiz Sentença é uma forma sentencial sem não-terminais Linguagem é o conjunto de todas as sentenças geradas pela gramática h) Reconhecedores: São dispositivos de aceitação da linguagem Componentes: :texto de entrada;cursor de leitura; máquina de estados; memória auxiliar; indicação de reconhecimento; Configuração do reconhecedor: estado corrente; posição do cursor e conteúdo do texto de entrada; conteúdo da memória auxiliar Tipos: determinísticos - um único movimento possível por configuração; não-determinísticos - podem apresentar mais de um movimento Reconhecimento: Configuração inicial; estado inicial único; cursor no início do texto de entrada; memória auxiliar com conteúdo conhecido. Configuração final: estado pertencente ao conjunto de estados de aceitação; cursor aponta além da cadeia de entrada; conteúdo da memória auxiliar atende a critério pré-estabelecido Aceitação: parte-se de uma configuração inicial; executam-se movimentos sucessivos da máquina de estados; atinge-se uma configuração final i) Observações - Linguagens dos tipos 2 e 3 têm sido as de maior interesse; Reconhecedores determinísticos têm preferência; autômatos finitos mínimos para linguagens do tipo 3; reconhecedores LL(k) e LR(k) para linguagens do tipo 2; Linguagens do tipo 1 estão ganhando espaço; gramáticas de atributos para linguagens do tipo 1; Há uma crescente tendência à automatização da obtenção de reconhecedores a partir de definições formais da linguagem; A dificuldade de formalização da semântica ainda é o maior obstáculo a esta atividade
PCS-2427 - Lógica Computacional – Aula 2 – prof. João José Neto Assunto: Conjuntos. Relações. Funções. Fechos. Conjuntos
conjuntos são coleções de objetos cada objeto é um membro ou elemento do conjunto conjuntos contêm cada um de seus elementos aL não há elementos repetidos em um conjunto conjuntos iguais contêm os mesmos elementos conjuntos unitários contêm um só elemento {a} a. o conjunto vazio não contém elemento algum = {} conjuntos infinitos contêm infinitos elementos = {0,l,...}
B é subconjunto de A se todos os elementos de B forem também elementos de A. B A Conjuntos podem ser dados por regras que definem as propriedades de seus elementos {x | x>0} C é a união de A e B se todos os seus elementos pertencerem ou a A ou a B, C=AB C é a intersecção de A e B se todos os seus elementos pertencerem a A e a B, C=AB C é a diferença entre A e B se seus elementos pertencerem a A, mas não a B, C=A -B
L = {a,b,c}
Idempotência - um conjunto não se altera sob união ou intersecção consigo mesmo Comutativa - a ordem dos conjuntos não altera o resultado das operações de união ou intersecção Associativa - a seqüência de aplicação de operações de união (ou de intersecção) a três conjuntos é irrelevante Distributiva - vale a distributividade para a união em relação à intersecção e viceversa Absorção - um conjunto não se altera sob união (intersecção) com o resultado de sua intersecção (união) com outro conjunto
Leis de De Morgan - a diferença entre um conjunto e uma união (intersecção) de outros dois é igual à intersecção (união) das diferenças entre esse conjunto e cada um dos outros dois
cartesiano Ênupla ordenada (al,a2, ... , an) Seqüência é uma ênupla ordenada em que não está fixado o número de elementos componentes Comprimento de uma seqüência é o número de seus elementos Produto cartesiano AlA2...An é o conjunto de todas as possíveis ênuplas ordenadas (al,a2, ... ,an) tais que ai Ai Uma relação n-ária sobre A1, A2, ... ,An é um subconjunto qualquer de A1A2 ... An Funções Uma função f: A B, de A para B, é uma relação binária R sobre A e B tal que para cada aA existe um e só um par ordenado de R, cuja forma seja (a,x). O conjunto A é o domínio de f. Para aA denota-se como f(a) o elemento bB tal que (a,b) f, f(a) é dito imagem do elemento a, segundo f. Se f: AlA2...An B é função, e f(al,a2, ... ,an) = b, então os ai são chamados argumentos de f, e b é o correspondente valor de f. f: A B é injetora se para todo a b, f(a) f(b) f: A B é sobrejetora se cada elemento de B é imagem de algum elemento de A f: A B é bijetora se for injetora e sobrejetora Uma relação binária R AB tem uma relação inversa R-1 BA dada por (b,a) R-1 (a,b) R A inversa de uma função nem sempre é função
Para relações binárias Q e R, define-se composição Q◦R ou QR como sendo o conjunto: Q◦R = { (a,b) | para algum c, (a,c) Q e (c,b) R}
Uma relação R AA pode ser representada através de um grafo orientado Elementos de A correspondem aos nós do grafo
Conjunto-potência de A (2A) é o conjunto de todos os possíveis subconjuntos de A Partição de A é qualquer subconjunto de 2A que não inclua o conjunto vazio, que tenha elementos disjuntos dois a dois e que seja tal que a união de todos os seus elementos seja A Teoremas de De Morgan A - (BC) = (A -. B) (A - C) A - (BC) = (A - B) (A - C) Absorção A(AB) = A A(AB) = A
Uma relação é de ordem parcial se e somente se for reflexiva e transitiva, e isenta de ciclos não-triviais Fechamentos Se D é um conjunto e n 0, seja R Dn+1 uma relação (n+l)-ária sobre D. Então um subconjunto B D é dito fechado em relação a R sempre que (bl, ... , bn+1) R, caracterizando uma propriedade de fechamento de B. Seja P uma propriedade de fechamento definida por relações sobre um conjunto D, e seja A D. Nessas condições, existirá um conjunto mínimo B, que contém o conjunto A. e que guarda a propriedade P. B é o fechamento de A em relação às relações Rl ... Rn No particular caso de R AA define-se R* como fechamento reflexivo e transitivo de R. O fechamento reflexivo e transitivo R* é dado por: R { (a,b) | existe uma cadela de a para b, em R} Relação binária pode ser fechada para uma ou mais propriedades. Ex.: R+ fechamento transitivo Conjuntos Finitos e Infinitos
Se f for uma bijeção, f -1 também será uma bijeção Em bijeções simples, em que na prática o argumento pode ser confundido com sua imagem, caracterizam-se os isomorfismos naturais
Relações Binárias Especiais A e B são disjuntos se não tiverem intersecção Uniões e intersecções se aplicam também a mais de dois conjuntos
Uma cadeia é um ciclo se os ai são distintos, e também (an,a1) R Um ciclo é trivial se n=1. Se não, será não-trivial
R AA é reflexiva se todo (a,a) R R AA é simétrica se (a,b) R sempre que (b,a) R R AA é anti-simétrica se para todo (a,b) R , com ab, implicar que (b,a) R R AA é transitiva se (a,b) R (b,c) R (a,c) R Uma relação reflexiva, simétrica e transitiva é dita relação de equivalência Cada grupo de nós conexos do grafo forma uma classe de equivalência As classes de equivalência de uma relação de equivalência sobre A criam uma partição de A
Relações
Uma relação reflexiva, anti-simétrica e transitiva é chamada relação de ordem parcial Uma relação de ordem parcial R AA é chamada relação de ordem total se, para todo a, b A, tem-se que ou (a,b) R ou (b,a) R
Par ordenado (a,b) distingue os elementos a e b Produto cartesiano AB de A por B é o conjunto de todos os possíveis pares ,ordenados (a,b) tais que aA e bB Uma relação binária sobre dois conjuntos é qualquer subconjunto de seu produto
Uma cadeia em uma relação binária é uma seqüência (al,a2, ... ,an), n 1, tal que (ai, ai+1) R, i = 1, ... , n-1. Diz-se que esta cadeia vai de a1 até an
Tamanho (número de elementos) finito caracteriza conjuntos finitos. Dois conjuntos finitos A e B são equinumerosos se for possível obter alguma bijeção f: A B. É uma relação de simetria. Um conjunto finito é equinumeroso em relação a {l, ..., n}, com n . Neste caso, diz-se que a cardinalidade do conjunto é n. Para conjuntos infinitos não é possível contar os elementos, Um conjunto é enumeravelmente infinito se for equinumeroso em relação a . Um conjunto é enumerável se for finito ou então enumeravelmente infinito. Caso contrário será dito não-enumerável. A forma mais direta de mostrar que um conjunto é enumerável consiste em estabelecer uma bijeção deste conjunto com outro conjunto enumerável, como por exemplo o conjunto dos naturais. Uma união finita de conjuntos enumeráveis é enumerável. Um produto cartesiano de um número finito de conjuntos enumeráveis é enumerável.
Material de Apoio para esta aula: Lewis e Papadimitriou – Elements of the theory of computation. Existe a tradução para o português, da Bookman, Porto Alegre: Elementos de teoria da computação, 2a. edição. CUIDADO: Utilizar apenas a “versão totalmente revisada”, de 2004. Harrison – Introduction to formal language theory – Addison Wesley, 1978. Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009.
PCS-2427 - Lógica Computacional – Aula 3 – prof. João José Neto Assunto: Representação finita de linguagens Logo existe um número infinito, enumerável, de representações para linguagens O conjunto de linguagens possíveis sobre um alfabeto é 2* Esse conjunto é não-enumerável de acordo com o teorema de Cantor Assim, há linguagens que não são finitamente representáveis, independentemente da forma escolhida para sua representação. Algumas representações usuais de linguagens: expressões regulares, para linguagens regulares geradores ou gramáticas reconhecedores ou autômatos algoritmos Fechamentos FECHAMENTO TRANSITIVO - conjunto de todas as cadeias nãovazias sobre um dado alfabeto se omitir o símbolo “°”: w=xy FECHAMENTO REFLEXIVO E TRANSITIVO – além das cadeias A concatenação é associativa, não-comutativa e seu elemento neutro é compreendidas no fechamento transitivo, inclui a cadeia vazia a cadeia vazia. Fechamentos podem ser aplicados a operadores, indicando sua Uma cadeia v é sub-cadeia de outra cadeia w se e somente se repetida aplicação existirem x e y tais que w=x°v°y. Se w = x°v, v é sufixo de w Gramáticas Dispositivos de geração de sentenças Se w = v°y, v é prefixo de w Componentes Para cada natural i e cada cadeia w define-se indutivamente: vocabulário da gramática (terminais e não-terminais) 0 i+1 i w =; w =w°w terminais da gramática (átomos da linguagem) Define-se cadeia reversa wR de uma cadeia w: símbolo inicial ou raiz da gramática (não-terminal) R Se w = , então w = w = . produções da gramática (regras de substituição) Se |w| = n+1 > 0, e w=u° para , então wR=°uR Derivações Derivação direta é o resultado da aplicação de uma produção apenas (demonstra-se por indução) Forma sentencial – qualquer cadeia sobre o vocabulário da gramática, que seja derivável a partir da raiz Um conjunto de cadeias sobre (um subconjunto de *) Sentença é uma forma sentencial isenta de não-terminais é chamado linguagem. Linguagem é o conjunto de todas as sentenças geradas pela gramática Linguagens infinitas são conjuntos do tipo Alfabetos e Linguagens Alfabetos e linguagens podem ser usados como modelos para os dados que o computador manipula, na forma de cadeia de símbolos. O alfabeto binário {0,1} é particularmente útil. Uma cadeia sobre um alfabeto é uma seqüência finita de símbolos do alfabeto A cadeia vazia não contém símbolos. * é o conjunto de todas as cadeia sobre o alfabeto Comprimento de uma cadeia é o número de símbolos da seqüência que a compõe Um mesmo símbolo s pode ocorrer mais de uma vez na mesma cadeia Concatenação w de duas cadeias x e y é a cadeia formada pela justaposição de x com y: w=x°y Não havendo ambigüidade, pode-
L={ w* | w tem a propriedade P} Se é finito,* será um conjunto infinito enumerável (prova-se construindo uma bijeção, através da enumeração de * de acordo com alguma ordenação lexicográfica) Pode-se definir para linguagens L, L’: Complemento de uma linguagem *-L Concatenação de linguagens L°L’ Fechamento de Kleene de uma linguagem L* Fechamento transitivo L+=L°L* Representação finita de linguagens Representações de linguagens são cadeias finitas, sobre um alfabeto finito, destinadas a definir linguagens.
Reconhecedores São dispositivos de aceitação da linguagem Elementos componentes: texto de entrada cursor de leitura máquina de estados memória auxiliar indicação de reconhecimento Configuração do reconhecedor estado corrente posição do cursor e conteúdo do texto de entrada conteúdo da memória auxiliar
Tipos de reconhecedores determinísticos - um único movimento possível em cada config. não-determinísticos - mais de um movimento possível Reconhecimento Configuração inicial estado inicial único cursor no início do texto de entrada memória auxiliar com conteúdo conhecido Configuração final estado pertencente ao conjunto de estados de aceitação cursor aponta além da cadeia de entrada conteúdo da memória auxiliar atende a critério pré-estabelecido Aceitação parte-se de uma configuração inicial executam-se movimentos sucessivos da máquina de estados atinge-se uma configuração final Observações Gramáticas e Reconhecedores são formas alternativas de representação de linguagens Linguagens dos tipos 2 e 3 têm sido as de maior interesse Reconhecedores determinísticos têm preferência autômatos finitos mínimos para linguagens do tipo 3 reconhecedores LL(k) e LR(k) para linguagens do tipo 2 Linguagens do tipo 1estão ganhando espaço Há uma crescente tendência à automatização da obtenção de reconhecedores a partir de definições formais da linguagem A dificuldade de formalização da semântica ainda é o maior obstáculo à utilização prática da semântica formal. Material de Apoio para esta aula:
Lewis e Papadimitriou – Elements of the theory of computation. Existe a tradução para o português, da Bookman, Porto Alegre: Elementos de teoria da computação, 2a. edição. CUIDADO: Utilizar apenas a “versão totalmente revisada”, de 2004. Harrison – Introduction to formal language theory – Addison Wesley, 1978. Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009.
PCS-2427 - Lógica Computacional – Aula 4 – prof. João José Neto Assunto: Técnicas de demonstração: Contradição, Indução, Princípio da casa de pombos, Diagonalização. Algumas Técnicas Importantes de Demonstração Há vários tipos de demonstrações, baseados nos seguintes princípios: (a) Principio da contradição ou redução ao absurdo A essência deste princípio consiste em basear a demonstração de uma afirmação X na negação de X, ou seja, parte-se da hipótese de que seja verdadeira a negação daquilo que se deseja demonstrar. Depois, através de manipulação lógica, prova-se algo que seja uma contradição, ou seja, prova-se como insustentável a hipótese formulada (negação de X), portanto conclui-se que X só pode ser verdadeira, já que sua negação implica alguma afirmação inconsistente ou absurda. (Ver exemplo 1.48 do livro Linguagens Formais, página 51.) (b) Principio da indução matemática Seja A um subconjunto dos números naturais tal que 0 A e para cada natural n, se {0,1, ..., n} A. então n+1 A. Nessas condições tem-se A=. Usa-se para provar asserções do tipo: "Para todo natural n, a propriedade P é válida". Para isso, deve ser provada a validade de: (1) Base da indução - provar que P vale para n=0. (2) Hipótese de indução: admitir que P vale para os números naturais 0,1,..., n. (3) Passo indutivo: provar que P é válido também para n+1.
(Ver exemplos: 1.45 a 1.47 do livro Linguagens Formais, páginas 48 a 50; 1.5.1 e 1.5.2 do livro Elementos da teoria da computação, páginas 37 e 38.)
Teorema de Cantor Seja A um conjunto qualquer, enumerável por bijeção com o conjunto dos números naturais. Nessas condições, o conjunto-potência de A não será enumerável por bijeção com o conjunto dos números naturais.
(c) Principio das Casas de Pombos Se A e B forem conjuntos finitos não-vazios, e se a cardinalidade de A for maior que a de B, então não haverá nenhuma função injetora de A para B (prova-se por indução).
(Ver, como exemplos do uso deste princípio, o exemplo 1.5.3 do livro Elementos da Teoria da Computação, páginas 39 e 40, e a demonstração do famoso teorema de Cantor, nas páginas 40 e 41)
Teorema: se R é uma relação binária sobre um conjunto A finito, caso haja em R cadeias arbitrariamente longas, então certamente haverá ciclos em R (prova-se pelo princípio das casas de pombos)
Para um pequeno estudo adicional sobre a teoria de Cantor, acerca da enumerabilidade de conjuntos, e da cardinalidade de conjuntos infinitos, leia o cap. 1.7 do livro Linguagens Formais, páginas 51 a 57.
(Ver, como exemplo, o teorema 1.5.1 do livro Elementos da teoria da computação, página 39)
Bibliografia de Apoio para esta aula:
Lewis e Papadimitriou – Elements of the theory of computation. Existe a tradução para o português, da Bookman, Porto Alegre: Elementos de teoria da computação, 2a. edição, mas CUIDADO: Utilizar apenas a “versão totalmente revisada”, de 2004.
Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009.
(d) Principio da diagonalização Sendo B uma relação binária sobre um conjunto C, define-se D como conjunto diagonal de C para a relação R, como sendo o conjunto de todos os elementos de C tais que, sendo c um elemento de C, o par (c, c) não pertence à relação R. Para cada elemento c do conjunto C, seja Rc = {c’ | c’ C e (c, c’) R}. Nessas condições, o princípio da diagonalização garante que D será diferente de todos os elementos de Rc. Este princípio da diagonalização é pouco empregado na matemática, mas tem um papel importante na demonstração de muitos fatos essenciais da teoria da computação.
PCS-2427 – Lógica Computacional – Aula 5 – Prof. João José Neto Assunto: Expressões Regulares. Linguagens Regulares. Expressões Regulares * (fechamento reflexivo e transitivo, ou fechamento de Kleene, ou “estrela” de Kleene) é o conjunto de todas as possíveis cadeias que se pode formar sobre o alfabeto * inclui a cadeia vazia que não contém símbolos Qualquer conjunto de cadeias sobre (sempre um subconjunto de *) é chamado linguagem. * é um conjunto-universo no domínio das linguagens. Linguagens regulares sobre um alfabeto são conjuntos de cadeias formadas a partir de elementos de através do uso único das operações de concatenação, união de conjuntos e fechamento de Kleene Expressões regulares constituem uma forma precisa de definição para as linguagens regulares. Álgebra das Expressões Regulares Def. Conjunto Regular sobre um alfabeto {a1 ,..., an} é qualquer conjunto que se possa formar com os elementos de aplicando-se-lhes uma seqüência conveniente de regras escolhidas dentre as seis seguintes 1. { } (o conjunto vazio de cadeias) é um conjunto regular por definição 2. { } (o conjunto unitário que contém apenas a cadeia vazia) é um conjunto regular por definição 3. {a1}, ... , {an} (os conjuntos unitários de cadeias de comprimento unitário) são conjuntos regulares, também por definição 4. Se L1 e L2 forem conjuntos regulares, então é também regular o conjunto L1L2 que representa sua concatenação 5. Se L1 e L2 forem conjuntos regulares, então é também regular o seu conjunto união L1L2
6. Se L1 for um conjunto regular, então é também regular o conjunto L1* que representa seu fechamento de Kleene Def. Expressão Regular sobre o alfabeto {a1 ,..., an} é uma cadeia de símbolos formada pela aplicação, aos elementos de , de uma seqüência adequada de regras, escolhidas dentre as seis seguintes:: 1. é a expressão regular que representa o conjunto regular { } 2. é a expressão regular que representa o conjunto regular { } 3. a1, ... an são expressões regulares, que simbolizam os conjuntos regulares {a1} , ... , {an}, respectivamente 4. Se R1 e R2 forem duas expressões regulares, correspondentes aos conjuntos regulares L1 e L2, então R1R2 é também uma expressão regular, a qual representa o conjunto regular L1L2 5. Se R1 e R2 forem duas expressões regulares correspondentes aos conjuntos regulares L1 e L2, então R1 | R2 é também uma expressão regular, que representa o conjunto regular L1L2 6. Se R1 for uma expressão regular, correspondente ao conjunto regular L1, então R1* será a expressão regular que representa o conjunto regular L1* Convenções de notação Para tornar mais legível a notação, convenciona-se uma precedência entre os operadores utilizados: * tem a máxima precedência, seguido de , e finalmente | . Parênteses são usados para alterar essa precedência se necessário. Parênteses usados em conformidade com essa precedência podem ser omitidos, assim como o par que envolve toda a expressão.
A simples justaposição pode substituir o sinal de concatenação. Def. Sendo R uma expressão regular, a linguagem representada por R é denotada por L (R). Duas expressões regulares R1 e R2 são ditas equivalentes quando representarem a mesma linguagem, ou seja, quando L (R1) =L (R2), e o fato é denotado por R1=R2. Propriedades das expressões regulares Prova-se que as seguintes igualdades sempre valem: 1. R1 | = R1 2. R1 = R1 = R1 3. R1 = = R1 4. R1 | R2 = R2 | R1 5. R1 | R1 = R1 6. R1 | (R2 | R3) = (R1 | R2) | R3 7. R1 (R2 R3) = (R1 R2) R3 8. R1 (R2 | R3) = (R1 R2) | (R1 R3) 9. * = 10. * = 11. (R1 | R2)* = (R1* | R2*)* 12. (R1 | R2)* = (R1* R2*)* 13.(R1*)* = R1* 14.(R1*)(R1*) = R1* Por outro lado, há exemplos de conjuntos para os quais: 1. R1 | R1 2. R1 R2 R2 R1 3. R1 R1 R1 4. R1 | (R2 R3) (R1 | R2) (R1 | R3) 5. (R1 R2)* (R1* R2*)* 6. (R1 R2)* (R1* | R2*)*
PCS-2427 - Lógica Computacional – Aula 6 – prof. João José Neto Assuntos desta aula: Hierarquia de Chomsky e Gramáticas regulares Hierarquia de Chomsky Em seu estudo sistemático de linguagens formais, Chomsky definiu uma hierarquia que consta de quatro diferentes classes de linguagens, denominadas linguagens dos tipos 0, 1, 2, 3. Tipo 0 – linguagens gerais Tipo 1 – linguagens sensíveis ao contexto Tipo 2 – linguagens livres de contexto Tipo 3 – linguagens regulares. As mais simples são do tipo 3 (regulares), e as mais complexas, do tipo 0 (gerais). Linguagem tipo 0 Linguagem tipo 1 Linguagem tipo 2 Linguagem tipo 3
Linguagens regulares ou do tipo 3: Na aula anterior essas linguagens regulares já foram definidas e estudadas do ponto de vista dos conjuntos, e também do ponto de vista das expressões regulares. Nesta aula estudam-se as linguagens regulares do ponto de vista de um mecanismo generativo ou gramatical. Definição gramatical de linguagens regulares: A partir do alfabeto, usando apenas concatenações, uniões de conjunto e fechos de Kleene, formam-se todas as sentenças de qualquer linguagem regular. Portanto, gramáticas regulares devem permitir a definição de sentenças de forma análoga, aplicando regras sujeitas a essa mesma restrição. As gramáticas regulares podem assumir diversas formas, sendo as mais populares aquelas chamadas gramáticas lineares. Gramáticas lineares (à direita / à esquerda): São aquelas que definem cadeias que crescem sempre no mesmo sentido (direita/esquerda, respectivamente), por meio da justaposição sucessiva de novos elementos do alfabeto a uma cadeia já construída. Para isso, as gramáticas lineares devem fornecer elementos para:
definir ao menos uma regra gramatical que defina uma cadeia inicial que servirá como ponto de partida para que novos símbolos possam ser justapostos. justapor a uma cadeia existente novos elementos do alfabeto. construir cadeias arbitrariamente longas a partir da sucessiva justaposição de instâncias de cadeias já construídas. Gramáticas lineares Def. Gramática linear à direita (esquerda) sobre um alfabeto {a1, ... , an} é uma quádrupla G=(V,,P,S), onde 1. é o conjunto finito não-vazio de terminais da gramática, e seus elementos são os componentes das sentenças da linguagem que G define. 2. Define-se N como sendo o conjunto de não-terminais da gramática G, e seus elementos são todos os símbolos utilizados na gramática que não sejam terminais. 3. S é um símbolo não-terminal, único e diferenciado, denominado raiz da gramática G. 4. V é um conjunto finito não vazio denominado vocabulário da gramática G. Os elementos de V podem ser terminais ou nãoterminais: V=N 5. P é o conjunto das produções ou regras de produção de G, ou seja o conjunto de possíveis substituições dos não-terminais. Essas regras constituem as leis de formação das sentenças da linguagem definida por G. 6. Cada regra de P assume uma das formas seguintes: A B (ou A B ), com AN, BN{}, e * A restrição de haver apenas um não-terminal por regra é forte, e a isso se acrescenta o fato de que esse não terminal deve aparecer sempre na extremidade direita (esquerda) da expressão, daí o nome linear à direita (esquerda). Def.: Forma sentencial é qualquer cadeia, formada de símbolos do vocabulário V da gramática, que se pode construir a partir da raiz S da gramática pela aplicação sucessiva de regras do conjunto de produções P. Por definição, S é uma forma sentencial. Def. Uma sentença da linguagem definida por uma gramática linear G é qualquer forma sentencial composta apenas de terminais. Def. Um passo de derivação consiste na geração de uma nova forma sentencial pela aplicação de alguma regra do conjunto P a uma forma sentencial dada. Diz-se nesse caso que a nova forma sentencial deriva diretamente daquela. Def. Derivação de uma sentença é a seqüência de todas as formas sentenciais utilizadas na construção de uma sentença a partir da raiz da gramática.
Def. Árvore de derivação de uma sentença é uma representação gráfica do conjunto de passos de derivação que constituem a derivação dessa sentença. A raiz da árvore de derivação é o nãoterminal S (raiz da gramática), e o contorno formado apenas pelas folhas dessa árvore, lidas visitando os nós da árvore da esquerda para a direita, forma a sentença em questão. Observe-se que para gramáticas lineares à direita a árvore de derivação terá a aparência de uma linha inclinada descendente, com os terminais anexados ao longo dessa linha, enquanto para as gramáticas lineares à esquerda, a aparência é idêntica, porém a linha é ascendente. Observe-se ainda que em nenhum estágio intermediário da derivação podem coexistir dois ou mais não-terminais nas formas sentenciais e portanto nunca ocorrerão árvores de derivação incompletas que representam as formas sentenciais, que apresentem mais de um único não-terminal. Prova-se que o conjunto de todas as linguagens geradas por gramáticas lineares à direita é o mesmo que o gerado por gramáticas lineares à esquerda. Este conjunto coincide com o das linguagens representadas através de expressões regulares. É o conjunto das linguagens regulares, ou do tipo 3 segundo a classificação de Chomsky. Chama-se gramática regular, ou do tipo 3, àquela que for linear à direita ou linear à esquerda. Derivações em gramáticas lineares: Partindo de uma cadeia (forma sentencial) inicial que contém apenas o não-terminal S (raiz da gramática), aplicam-se as regras gramaticais de substituição do não-terminal , contidas no conjunto P. Só podem ocorrer duas situações: Ou contém um não-terminal, que deverá ser substituído aplicando-se em seguida alguma regra de P. Como todas as regras desse tipo podem apenas conter um não-terminal, então continuará restando um não-terminal apenas a ser substituído. Ou não contém não-terminais, e nesse caso o único nãoterminal que restava a ser substituído não mais existe, terminando assim a derivação. Notar que durante toda a derivação, as gramáticas lineares mantêm um único não-terminal a ser substituído, e esse não-terminal permanece sempre na mesma extremidade das diversas formas sentenciais. Material de Apoio para esta aula: Lewis e Papadimitriou –Elementos de teoria da computação, 2a. edição. versão totalmente revisada. Bookman, Porto Alegre: 2004. Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009.
PCS 2427 – Lógica Computacional – Aula 7 – Prof. João J. Neto Assunto: Propriedades das linguagens aceitas por autômatos finitos. Teste de Regularidade e teorema do bombeamento. O não-determinismo não altera o poder dos autômatos finitos Teorema 1 − A classe das linguagens aceitas pelos autômatos finitos é fechada em relação à união, à intersecção, à estrela de Kleene, à complementação e à intersecção. Demonstra-se simulando um autômato que aceite a linguagem apropriada. • União: transições em vazio do estado inicial para os estados iniciais dos autômatos originais; unir os estados finais dos dois autômatos • Concatenação: estado inicial do primeiro, transição em vazio dos estados finais do primeiro para o inicial do segundo, estados finais do segundo • Fechamento de Kleene: novo estado, inicial e final; transição em vazio para o estado inicial do autômato original, transições em vazio do estado final do autômato original para o novo estado inicial. • Complemento: mesmo estado inicial; os estados finais são apenas aqueles que não eram finais no autômato original. • Intersecção: complementar a união dos complementos das linguagens (aplicação do teorema de De Morgan)
Teorema 2 − Existem algoritmos para resolver as seguintes questões: Dado um autômato finito M, e uma cadeia w, w ∈ L(M)? Basta verificar que, em uma versão determinística de M, é possível reconhecer w em |w| movimentos. Dado um autômato finito M, L(M) = ∅ ? Verificar se inexiste caminho do estado inicial para algum estado final no grafo que representa o autômato finito. Dado um autômato finito M, L(M) = Σ * ? Verificar se o complemento é vazio. Dados dois autômatos finitos M1 e M2, L(M1) ⊆ L(M2) ? Verificar se (Σ Σ*- L(M2)) ∩ L(M1) = ∅. Dados dois autômatos finitos M1 e M2 , L(M1) = L(M2) ? Verificar se L(M1) ⊆ L(M2) ∧ L(M2) ⊆ L(M1). Teorema 3 − Uma linguagem é regular se e somente se for aceita por algum autômato finito.
Condição suficiente: A classe das linguagens regulares é a menor classe de linguagens que inclui ∅ e {σ σ}, e é fechado em relação a ∪, ∩ e ° . É trivial obter autômatos que aceitem o conjunto vazio e o conjunto unitário. Linguagens reconhecidas pelos autômatos finitos são fechadas em relação a ∪, ∩ e ° , então toda linguagem regular é aceita por um autômato finito Condição necessária: Dado um autômato finito M qualquer, deve-se mostrar que existe uma linguagem regular R, que é a linguagem por ele aceita R=L (M) Prova-se por indução que os conjuntos R(i,j,k) de cadeias de Σ* que levam M de um estado qi para um estado qj qualquer, sem passar por estados de índice maior ou igual a k, são sempre regulares, logo sua união, que compõe a linguagem R, também será regular Testes de Regularidade Para mostrar que uma linguagem é regular, é suficiente representá-la através de expressões regulares ou de autômatos finitos. Linguagens regulares exigem uma quantidade fixa de memória para serem reconhecidas. Linguagens regulares com número infinito de cadeias exibem apenas um certo número de construções repetitivas concatenadas, excluindo-se, portanto, desta classe, as linguagens mais complexas. Teorema 4 (do bombeamento) − Seja L uma linguagem regular infinita. Existem, neste caso, cadeias x, y, z tais que y ≠ ε , e xymz ∈ L para todo m ≥ 0 A argumentação pode ser baseada no fato de que cadeias infinitas sobre relações binárias finitas implicam na presença de ciclos. Este importante teorema é da classe dos teoremas de bombeamento Exercícios 1. Demonstrar detalhadamente os vários casos do teorema 2, acima enunciados. 2. Demonstrar, usando o teorema do bombeamento, que as linguagens da forma anbn ou a2n+3bcn não são regulares (invente outras linguagens, regulares e não-regulares, para exercitar este problema).
PCS 2427 – Lógica Computacional – Aula 8 – Prof. João J. Neto Assunto: Determinismo em autômatos finitos • Dado
• Aplica-se
•
•
um autômato, este geralmente apresenta com não-determinismos, transições em vazio e estados redundantes. É possível, nesse caso, aplicar ao autômato procedimentos de eliminação de transições em vazio e de outros não-determinismos presentes, bem como algoritmos de eliminação de estados equivalentes.
• Eliminação de Transições em Vazio • Transições em vazio geram caminhos alternativos válidos em um autômato, tornando-o
não-determinístico. Isso é indesejável, logo convém eliminar transições em vazio. eliminar-se uma transição em vazio, para não alterar a linguagem reconhecida, o estado-origem desta transição deve absorver cópias de todas as transições que emanam do seu estado-destino. Adicionalmente, se o estado-destino for um estado final, o estado-origem deve absorver também este atributo. Repete-se o procedimento para cada uma das transições em vazio presentes no autômato. O estado de origem deve incorporar todas as transições que partem de cada estado destino, podendo-se então descartar a coluna das transições em vazio. Em autômatos representados tabularmente, as células da linha correspondente ao estado de origem devem incorporar todas as informações que constam nas células das colunas correspondentes, da linha associada ao estado de destino (“merge”). Pode-se estabelecer o seguinte procedimento para a eliminação de transições em vazio de uma tabela de transições: • Efetuar uma operação de “merge” das linhas que correspondam aso estados-destino de cada transição em vazio presente na tabela (esta operação pode eventualmente acrescentar novas transições em vazio ao estado-origem em estudo) • Repetir enquanto houver transições em vazio que não tenham sido eliminadas • O estado-origem deve passar a ser estado final do autômato se algum dos estados incorporados o for • Eliminar a coluna correspondente às transições em vazio • Eliminar eventuais estados inatingíveis após a operação.
• Eliminação de outros não-determinismos • Os eventuais não-determinismos remanescentes devem-se a transições múltiplas que
• Ao
• • •
• Estados Inatingíveis • Estados inatingíveis não contribuem para o reconhecimento da
linguagem, podendo ser descartados. Pode-se determiná-los construindo uma árvore de atingibilidade dos estados do autômato: • Inicia-se a construção da árvore de atingibilidade pela sua raiz, ou seja, pelo nó associado ao estado inicial do autômato. • Criam-se, para cada folha da árvore, nós-filhos associados aos estados-destino das transições que têm como origem o estado a ela associado, mas apenas para os estados-destino que não tenham ainda sido representados na parte da árvore já construída.
sucessivamente esta regra até que não seja mais possível acrescentar novos ramos à árvore Todos os estados do autômato que não estiverem representados nos nós da árvore construída são considerados nós inatingíveis, podendo ser eliminados do autômato, juntamente com todas as transições que os referenciem.
• • • • •
consomem um mesmo átomo a partir de um mesmo estado-origem, criando também caminhos múltiplos a serem eliminados. Nas tabelas de transições, isto se manifesta pela presença de mais de um estadodestino em alguma célula da tabela. Podem ser eliminados tais não-determinismos criando-se um estado auxiliar associado a cada um destes conjuntos de estados-destino alternativos. Os novos estados devem então incorporar todas as transições que emanam dos estados que compõem o conjunto de estados que lhes dá origem. Nas tabelas de transições, acrescenta-se uma nova linha para cada um desses novos estados, e se preenchem suas células com o “merge” das linhas associadas aos estados do conjunto (isto pode, por sua vez, fazer surgir novos não-determinismos, que devem ser eliminados um a um de forma análoga). Não existe o perigo de mais e mais estados surgirem indefinidamente, pois se o conjunto inicial de estados é finito, tem-se a certeza de que seu conjunto-potência também será finito.
• Chega-se
•
dessa maneira a um procedimento sistemático para a obtenção de um autômato finito determinístico: • Construir um autômato, da forma convencional • Eliminar suas transições em vazio • Eliminar suas transições não-determinísticas restantes • Eliminar os seus estados não-atingíveis Isso é suficiente para tornar determinístico o autômato. Se for conveniente, é possível ainda minimizar o autômato resultante, eliminando a redundância representada pela presença de estados equivalentes.
PCS-2427 - Lógica Computacional – Aula 09 – prof. João José Neto Motivação
Assunto: Minimização de Estados de Autômatos Finitos.
A importância do estudo de métodos para a minimização de autômatos finitos decorre de diversos fatores: É válido para a classe de linguagens definidas por autômatos finitos e não vale para outras linguagens; Extrapola interesses somente teóricos, mostrando-se útil para a obtenção prática de autômatos eficientes; É possível automatizar essa operação, por meio de um algoritmo aplicável a qualquer autômato inicial, gerando um único autômato mínimo a partir dele; Para cada linguagem regular é único o autômato finito mínimo correspondente, permitindo provar a equivalência de duas linguagens pela verificação da identidade entre seus autômatos finitos mínimos; Hipóteses O autômato inicial é determinístico, portanto um autômato isento de transições em vazio e também de múltiplas transições emergindo de um mesmo estado e consumindo um mesmo símbolo de entrada. O algoritmo de minimização consta das etapas seguintes: Eliminação de transições em vazio Eliminação das demais transições não-determinísticas Eliminação de estados inúteis e inacessíveis Identificação de estados indistinguíveis Agrupamento e fusão de estados equivalentes Princípio do método de minimização A idéia é particionar sistematicamente o conjunto de estados do autômato em grupos cada vez mais abrangentes, até que cada grupo tenha o maior número possível de estados, constituindo, portanto, uma classe de equivalência. Em seguida, em cada uma dessas classes de equivalência substituem-se todos os estados por um estado apenas, que represente toda a classe, descartando-se todos os demais. Identificação sistemática das classes de equivalência Definição: Dois estados de um autômato finito M são equivalentes se e somente se, para uma cadeia x qualquer, se a operação de M for iniciada em qualquer desses dois estados, tendo x como cadeia de entrada, então ou o autômato aceitará x em ambos os casos, ou então rejeitará x em ambos os casos. (E. F. Moore, "Gedanken-experiments on sequential Machines." in Automata Studies, ed. C. E. Shannon and J. McCarthy. Princeton University Press, 1956, 129 – 153) Estados indistinguíveis e equivalentes Indistinguibilidade de estados em autômatos finitos
Definição. Uma cadeia x distingue os estados q1 e q2 quando (q1, x) * (q3, ε) e (q2, x) * (q4, ε), e nesse caso, ou q3 é estado final ou q4 é estado final, mas não ambos. Definição. Dois estados q1 e q2 são k-indistinguíveis quando não existir nenhuma cadeia x, de comprimento k ou menor, que permita distinguir q1 e q2. Assim, a equivalência entre dois estados q1 e q2 ser identificada à sua kindistinguibilidade para qualquer valor de k. 0 Para k=0 (cadeia vazia), qi ≡ qj só se qi e qj forem ambos finais k k-1 Para k>0, qi ≡ qj se e só se qi ≡ qj e também k-1 δ(qi , σ) ≡ δ (qj , σ) ∀ σ ∈ Σ. Equivalência de estados em autômatos finitos Teorema. Para autômatos finitos com n estados, tem-se: q1 ≡ q2 ⇔ q1 ≡n-2 q2
Algoritmo: classes de equivalência Hipótese: o autômato original é determinístico. Divide-se o conjunto de estados original em dois grupos: o dos estados finais e o dos não-finais. Para cada grupo existente, refiná-lo de acordo com o seguinte critério: Dois estados são equivalentes se e só se aceitam o mesmo conjunto de entradas, sendo que para cada entrada ou os correspondentes estados-destino coincidem, ou então são equivalentes. Caso contrário, os dois estados não serão equivalentes, devendo pertencer portanto a grupos diferentes. Após analisar exaustivamente todos os pares de estados contidos nos grupos e refinar os grupos correspondentemente, resultam as classes de equivalência. Algoritmo: minimização de estados Construir as partições correspondentes às classes de equivalência de ordem 0, 1, 2, ... , k+1 até que as classes de ordem k e k+1 coincidam. Construir o autômato finito mínimo equivalente, tal que: O conjunto de estados seja o conjunto dessas classes de equivalência [q]. O conjunto de transições seja dado pela transição de uma classe de equivalência [q] consumindo o símbolo σ para a classe de equivalência [r] sempre que existir uma transição de q para r consumindo σ no autômato original. O estado inicial seja [q0] correspondente à classe que contém o estado inicial q0 do autômato original. O conjunto dos estados finais seja o conjunto das classes de equivalência que contenham algum estado final do autômato original. Material de Apoio para esta aula:
Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009. (p. 216-230)
PCS-2427 - Lógica Computacional – Aula 10 – prof. João José Neto Assunto desta aula: Equações envolvendo linguagens regulares
Equações envolvendo linguagens regulares Prova-se que para qualquer expressão regular é possível de forma metódica (algoritmicamente) construir um autômato finito que aceite a mesma linguagem que essa expressão regular representa. Isso decorre do fato de que qualquer linguagem aceita por um autômato finito constitui um conjunto regular sobre seu alfabeto (este teorema está formalmente demonstrado nas páginas 191-192 do livro Theory of Finite Automata) . Def. Equações envolvendo linguagens regulares são igualdades entre duas expressões regulares sobre conjuntos (coeficientes) e incógnitas que representam conjuntos (linguagens regulares). Coeficientes e incógnitas simbolizam linguagens regulares. Resolver uma equação desse tipo consiste em determinar, para a incógnita, uma expressão regular sobre o conjunto dos símbolos que não são incógnitas, tal que, substituindo-se a incógnita por tal expressão, a equação se transforme em uma identidade. Teorema 1 (ou Lema de Arden): Sendo Σ um alfabeto, sendo e subconjuntos de Σ , então a equação admite a linguagem como solução. Qualquer outra solução para esta equação obrigatoriamente conterá a linguagem representada por . Adicionalmente, se ε∉ , então será a única solução dessa equação. (encontra-se uma prova formal deste teorema no livro Theory of Finite Automata, pág. 185-186) Exemplo 1: tem como solução única solução desta equação, pois:
. Notar que
não é
≠
uma vez que a partir da expressão nunca será obtida uma cadeia que contenha o símbolo , embora isso possa ocorrer a partir da expressão
Exemplo 2:
ε
tem diversas soluções, entre as quais .
e
Isso ocorre por causa da presença de ε no coeficiente que contraria a hipótese do teorema 1.
Def. Um sistema de equações envolvendo linguagens regulares corresponde a um conjunto não unitário de equações, envolvendo mais de uma incógnita, ou seja, um conjunto de igualdades entre expressões regulares sobre conjuntos (coeficientes) e incógnitas, ambos simbolizando linguagens regulares. Resolver um sistema de equações dessa natureza consiste em determinar, para cada incógnita, uma expressão regular sobre os conjuntos (coeficientes) que não sejam incógnitas, tal que, substituindo-se, no sistema de equações, todas as incógnitas pelas expressões regulares que representam as respectivas soluções, o sistema se transforma em um conjunto de identidades. Sempre é bom lembrar que tanto as variáveis como as constantes dessas equações referem-se a linguagens regulares. Teorema 2: Seja incógnitas :
, e um sistema de
equações com
onde ε∉ ∀ . a) Este sistema tem solução única, b) Pode-se solucionar esse sistema combinando a técnica de resolução de uma equação com uma só incógnita com a técnica de resolução algébrica de sistemas de equações por eliminação sucessiva de variáveis e por substituição. (demonstrado nas páginas 189-190 do livro Theory of Finite Automata) Esse teorema sugere um método prático para solucionar sistemas dessa forma: Aplicando passo a passo uma das seguintes opções, eliminar uma a uma as variáveis do sistema, até que reste apenas a raiz da gramática, expressa apenas em função de símbolos do alfabeto: a) Para eliminar auto-dependências nas expressões que definem uma variável, usar o Lema de Arden. b) Para eliminar uma variável, substituir todas as suas instâncias por uma expressão que a defina em função das restantes e de símbolos do alfabeto. Exemplo 3:
ε ∅
ε,
Sendo
ε
e (eliminando-se Assim,
∅ ∅ ∅
)
ε
∅
ε∅ ε
ε
cuja única solução é
ε ∅
. ,
Substituindo na segunda equação, tem-se ∅
que também tem a solução única
ε
∅
, .
∅
Exercícios: 1) Resolva a equação: 2) Resolva a equação: 3) Resolva o sistema: ε} Resolva o sistema:
ε ε
ε
5) Crie outras gramáticas lineares a partir de situações práticas. Considerando o sistema de equações cujas incógnitas são seus não-terminais, resolva o sistema e obtenha para cada não-terminal uma solução na forma de expressão regular. 6) Na construção de compiladores, a operação de extração de identificadores, números inteiros, palavras reservadas e operadores faz parte da tarefa de análise léxica. Modele essa linguagem usando uma gramática linear, com um não-terminal para cada tipo de elemento extraído, e resolva o sistema de equações assim obtido. Material de Apoio para esta aula: capítulo 6.3 (p.185-200) do livro Carroll e Long – Theory of Finite Automata with an introduction to formal languages, Prentice-Hall International, 1989.
PCS 2427 – Lógica Computacional – Aula 11 – Prof. João J. Neto Assunto: Conversão de formato entre formalismos regulares Foi estudado que as linguagens regulares são construídas a partir de um alfabeto finito não-vazio, usando-se apenas concatenações, uniões e fechos de Kleene, e podem ser expressas de diversas formas equivalentes, tais como: conjuntos regulares (especificação do conjunto pelas suas propriedades) expressões regulares (formalismo gramatical) gramáticas lineares (formalismo gramatical) autômatos finitos não-determinísticos (formalismo de aceitação autômatos finitos determinísticos (formalismo de aceitação) autômatos finitos mínimos (formalismo de aceitação) sistemas de equações sobre linguagens regulares (formalismo algébrico) Havendo uma equivalência entre esses formalismos, torna-se interessante que, dispondo-se de uma especificação de linguagem em um desses formatos, se saiba convertê-los em outro formato, pois há sempre alguma dessas notações que se mostra mais conveniente na prática sobre as demais, conforme a situação particular em que se está trabalhando. Algumas conversões são óbvias, outras exigem um certo esforço para serem feitas. Vamos tratar apenas de algumas delas, que merecem uma atenção maior devido à maior complexidade que apresentam. Assim, vamos comentar acerca de como resolver as seguintes conversões: a) autômatos finitos para gramáticas lineares – para converter um autômato finito em uma expressão regular equivalente, basta seguir o seguinte procedimento: iniciar considerando o estado inicial do autômato; para cada estado do autômato, sendo m o estado de origem e n o estado de destino, e sendo s o símbolo consumido a partir de m (eventualmente a cadeia vazia ε), criar uma regra da forma m → s n (quando s=ε essa regra se reduz a m → n); para cada estado final m, acrescentar uma regra da forma m → ε . Obtémse assim uma gramática linear para a linguagem. b) autômatos finitos não-determinísticos para autômatos finitos determinísticos – há dois tipos de não-determinismo: transições em vazio ou transições para vários destinos consumindo o mesmo símbolo. Levanta-se o não determinismo em cada caso: Para cada transição em vazio do estado m para um estado n, incorporar transições com origem em m que consumam os mesmos símbolos que cada uma das transições que partem do estado n, e que tenham como destino os mesmos estados correspondentes. Em seguida, passa-se a eliminar o segundo tipo de transições:
estados que com um mesmo símbolo transitam para um mesmo estado ou para estados indistinguíveis deste. d) gramáticas lineares para sistemas de equações – uma simples mudança de notação. considerando cada não-terminal de uma gramática como se fosse uma variável, e cada terminal como uma constante, é possível agrupar os não-terminais da gramática como se estivéssemos colocando esses não terminais em evidência, fatorando sucessivamente as expressões até que cada não terminal seja expresso por expressão única, envolvendo terminais e não-terminais. Tem-se assim um sistema de equações regulares equivalente à gramática linear inicial. e) sistemas de equações para expressões regulares – método algébrico trivial para obtenção de expressões regulares e autômatos finitos. Partindo-se da raiz da gramática, e usando-se o método das substituições, eliminam-se referências não-recursivas a não-terminais. Aplicando-se o lema de Arden, eliminam-se autorecursões. Alternando-se esses dois processos até restar uma fórmula contendo apenas terminais, obtém-se uma expressão regular da linguagem. f) gramáticas lineares para autômatos finitos – é o processo dual do caso a). A raiz da gramática dá origem ao estado inicial do autômato. Para cada regra da forma m → s n, com m e n não-terminais, e s um símbolo do alfabeto, inclui-se a transição δ(m, s)=n na função de transição sendo m o estado de origem e n o estado de destino, e sendo s o símbolo consumido a partir de m. Se s=ε, inclui-se δ(m, ε)=n. Para regras do tipo m → ε, m se torna um estado de aceitação. g) autômatos finitos para expressões regulares – converte-se primeiro para uma gramática linear (como em a) e depois, para sistema de equações (como em d) e finalmente para expressões regulares resolvendo o sistema (como em e) h) expressões regulares para autômatos finitos – mapeia-se segundo as regras seguintes cada uma das formas que compõem as expressões regulares para autômatos finitos equivalentes: ε é mapeado como uma transição em vazio de um estado inicial para um de aceitação. O conjunto vazio corresponde a um estado inicial e um de aceitação, desconexos.
Um símbolo s do alfabeto se traduz em uma transição que consome o símbolo s um estado inicial e um de aceitação. Uma concatenação entre r e s se traduz na ligação do estado de saída do autômato correspondente a r ao estado de entrada do autômato que corresponde a s.
Para cada símbolo s, consumido por mais de uma transição, com destino a estados n com origem em um mesmo estado m, substituir o conjunto dessas transições por uma transição única de m para um novo estado m’ consumindo s, e a partir de m’ e, para cada transição que parte dos estados n com destino a estados n’, consumindo símbolos s’, criar as transições correspondentes partindo de m’, consumindo s’, com destinos n’. Depois de tratar todas as ocorrências desse tipo, eliminam-se todos os estados que não possam ser alcançados a partir do estado inicial do autômato.
Um fecho de Kleene sobre r leva de um estado único de entrada em vazio para o estado de aceitação e para o estado de entrada de r. Do estado de saída de r partem duas transições em vazio: uma para o estado de aceitação e outra para o estado de entrada de r.
c) autômatos finitos determinísticos para autômatos finitos mínimos – para esta conversão, eliminam-se estados equivalentes substituindo conjuntos de estados que formam classes de equivalência por um único estado, representante da classe:
i) expressões regulares para gramáticas lineares - obtêm-se primeiro a partir da expressão regular um autômato finito (como em h), depois este pode ser convertido para gramática linear (como em a)
separam-se em duas partições os estados finais e os não-finais refinam-se essas duas partições separando em partições menores conjuntos de estados que transitam com os mesmos conjuntos de símbolos refinam-se sucessivamente as partições restantes, mantendo em uma mesma partição somente estados indistinguíveis para cadeias de comprimentos cada vez maiores, ou seja,
Uma união entre r e s se traduz como um autômato que de um estado único de entrada tem transições em vazio para as entradas de r e de s, e dos estados de saída de r e de s, emergem transições em vazio com destino a um estado único de aceitação.
Material de Apoio para esta aula:
Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009. capítulos 3.3 até 3.8
PCS-2427 - Lógica Computacional – Aula 12 – prof. João José Neto Aninhamento sintático As linguagens regulares, que formaram o foco do estudo nesta disciplina até este ponto, baseavam-se na obtenção de sentenças sobre um alfabeto mediante a aplicação exclusiva de três operações: concatenação, união e estrela de Kleene e nada mais. As linguagens da prática, no entanto, necessitam mais que isso para serem devidamente representadas. Em particular, até as mais simples linguagens de programação exibem uma estrutura que não pode ser obtida aplicando-se exclusivamente estas três operações. Trata-se do aninhamento sintático, fenômeno lingüística em que pode ser identificada uma estrutura sintática formada pela concatenação de três sub-cadeias, sendo que as duas mais externas são não-vazias, e envolvem uma terceira, cujo formato é exatamente o mesmo da estrutura completa, comportando portanto uma nova sub-cadeia que contenha por sua vez outra estrutura completa e assim por diante, recursivamente. Formalmente, pode-se identificar em uma gramática a presença de aninhamentos sintáticos procurando-se não terminais X tais que X *AXB, com A ≠ε e B ≠ε. Em outras palavras, os aninhamentos sintáticos na definição de um não terminal X permitem que, durante uma derivação a partir de X, surja outra ocorrência de X, envolvida por cadeias A e B não vazias. Como nem A nem B são vazias, torna-se impossível a aplicação do lema de Arden, extensivamente utilizado para a eliminação de variáveis recursivas em equações com coeficientes regulares. No caso, o lema não se aplica, sendo portanto impossível eliminar a variável X em equações nas quais o aninhamento sintático se manifesta. São estas as chamadas auto-recursões centrais em X. Resta neste caso conviver com uma definição recursiva de X, com recursão não-eliminável. Extensões às expressões regulares Do ponto de vista algébrico, demonstra-se que é possível tratar esses termos auto-recursivos centrais em X como se fossem termos constantes nas equações obtidas a partir de gramáticas que exibem estruturas auto-recursivas centrais, ou seja, aninhamentos sintáticos. No entanto, ao escrever as expressões “regulares” correspondentes, surgem ocorrências de variáveis, ou seja, nãoterminais, contradizendo a definição de expressões regulares, que por hipótese somente podem exibir símbolos do alfabeto Σ, ou seja, constantes. Para contornar essa limitação, pode-se estender o conceito, definindo-se expressões regulares estendidas, as quais têm exatamente a mesma estrutura de uma expressão regular usual, exceto pela possibilidade de utilização de variáveis além das constantes. Adicionalmente, em contraste como as expressões regulares tradicionais, as expressões regulares estendidas admitem que lhes
Assunto: Aninhamento sintático seja associado um nome, correspondente ao não-terminal (variável) cuja sintaxe representam. Assim, uma expressão regular estendida cujo nome é X representa a forma geral da sintaxe representada pelo não-terminal X na gramática, e é definida através de uma auto-recursão central, sendo tal recursão denunciada pela presença do não-terminal X nessa expressão.
Extensões aos autômatos finitos Ao se tentar projetar um autômato finito para linguagens assim definidas, depara-se com uma dificuldade: os autômatos finitos, assim como as gramáticas regulares, não estão preparados para lidarem com não-terminais, e sabemos que não-terminais autorecursivos centrais, embora necessários no caso em questão, não são elimináveis. Assim sendo, é possível procurar uma forma de contornar o problema nos autômatos da mesma forma que foi feito nas expressões regulares: estendendo-os através do relaxamento da exigência de que todas as transições devam ser feitas consumindo-se um terminal (símbolo do alfabeto), e permitindo-se que sejam aceitas também transições especiais, que sejam capazes de “consumir” não-terminais. Entre aspas, significando que não se trata de uma operação da mesma consumo Embora essa interpretação possa à primeira vista parecer artificial, essas transições especiais têm um significado legítimo: “consumir” um não-terminal, por definição, significa consumir a maior subcadeia possível que respeite a sintaxe associada ao não-terminal em questão. Em outras palavras, é o mesmo que consumir uma sub-cadeia que leve de um estado inicial a um estado de aceitação o autômato finito estendido que reconhece a sintaxe associada a esse nãoterminal. Por analogia com as expressões regulares estendidas, tal autômato conteria transições em tudo iguais às dos autômatos finitos, exceto no caso daquelas que “consomem” não-terminais. A execução de uma destas transições equivale à execução do autômato estendido capaz de reconhecer o não-terminal a que se refere, consumindo de entrada uma sub-cadeia máxima. Autômatos com tais características podem ser construídos na forma de dispositivos recursivos, que ativam uns aos outros – da mesma forma como um programa aciona suas sub-rotinas ou funções – sempre que uma transição que “consome” não-terminal for percorrida. Ao final do reconhecimento dessa sub-cadeia, deve haver um retorno ao autômato de origem, para o exato estado de destino da transição que “consome” o não-terminal que provocou essa sua ativação recursiva – da mesma forma como, em programação, se efetua um retorno, após a execução de uma função ou de uma sub-rotina. Uma pilha é necessária para guardar esses “estados de retorno” em um autômato estendido desta natureza.
Autômato de pilha estruturado Generalizando esta idéia, pode-se considerar um sistema de equações mutuamente recursivas, e neste caso pode-se considerar uma expressão regular estendida como solução de cada uma das variáveis do sistema. Para cada uma dessas variáveis, associa-se um autômato finito estendido, que reconhece a sintaxe correspondente, eventualmente em função da sintaxe de outras variáveis. A solução do sistema de equações se reflete em uma família de autômato finitos estendidos mutuamente recursivos, que corresponde ao dispositivo reconhecedor para esse tipo de linguagem. Dá-se o nome de autômato de pilha estruturado a este dispositivo formado de um conjunto de submáquinas, cada qual implementando o reconhecimento da sintaxe de uma das variáveis do sistema. Uma pilha serve como repositório auxiliar para guardar estados de retorno pendentes. Prova-se que autômatos de pilha estruturados têm o mesmo poder dos autômatos de pilha convencionais, sendo capazes, portanto, de reconhecer linguagens com aninhamentos sintáticos. Assim, os autômatos de pilha estruturados reconhecem linguagens livres de contexto, da mesma forma que o fazem os autômatos de pilha tradicionais. Exercício Com base nos exemplos estudados em aula, e usando a técnica da resolução de equações com coeficientes regulares, obter expressões regulares estendidas e a partir delas, construir um autômato de pilha estruturado capaz de reconhecer a estrutura típica de uma linguagem de programação, dada pela seguintes regras gramaticais: → → → → ! → → " #$ % &' #$ () #$ → #$ →* ' $ #$ + * ' $ #$ ,* ' $ #$ - * ' $ *' $ → / 0 #$ 1 / → ! / / / 2
#$ .* ' $
Material de Apoio para esta aula: Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009, particularmente o capítulo 4.15 inteiro
PCS 2427 – Lógica Computacional – Aula 13 – Prof. João José Neto Assunto: Linguagens Livres de Contexto Um reconhecedor de linguagens é um dispositivo capaz de aceitar cadeias corretas (sentenças) da linguagem. É o caso dos autômatos. Um gerador de linguagens é um dispositivo capaz de sintetizar todas as sentenças de uma linguagem. É o caso das gramáticas. Adicionando-se a possibilidade de aninhamentos às linguagens regulares (concatenação, união e fecho de Kleene), obtém-se outra classe de linguagens, as linguagens livres de contexto. Gramáticas Livres de Contexto são gramáticas que permitem definir construções sintáticas contendo concatenação, união, fecho de Kleene e aninhamento sintático. Definem-se formalmente como quádruplas G=(V, Σ, P, S), com: V - alfabeto da gramática Σ - conjunto de terminais da linguagem V = N ∪ Σ N - conjunto de não-terminais N = V-Σ P - conjunto de produções P ∈ (V-Σ) × V* S - símbolo inicial (raiz) da gramática S ∈ N Para cada A ∈ N e u ∈ V*, escreve-se A →G u sempre que (A, u) ∈ P Para quaisquer u, v ∈ V*, escreve-se A G u se e só se houver cadeias x, y, v’ ∈ V* e A ∈ N tais que u=xAy, v=xv’y e A →G v’ A relação G* é o fechamento de Kleene para G L(G) é a linguagem gerada por G. L(G)= {w∈Σ ∈Σ*|S G* w} ∈Σ Uma linguagem L’ é livre de contexto se houver uma gramática G tal que L(G)=L’ Observações • Os símbolos →G e G podem ser abreviados como → e , respectivamente, sempre que G é subentendido no contexto. • Uma seqüência da forma w0 G w1 G ... G wn é dita uma derivação de wn a partir de w0 segundo a gramática G. • Cada wi é uma cadeia de V*. • n ≥ 0 é chamado comprimento da derivação. Constata-se facilmente que • Toda linguagem regular é livre de contexto (prove!) • Há linguagens livres de contexto não regulares (dê exemplos!) Exemplos de Gramáticas Livres de Contexto: São gramáticas livres de contexto (V,Σ,P,S): n n V={S,a,b}, Σ={a,b}, P={S→aSb, S→ε} gera a b , n≥0. • V={x,+,*,(,),E,T,F}, Σ={x,+,*,(,)}, S=E, •
P={E→E+T , E→T , T→T*F , T→F , F→x , F→ (E)} gera expressões aritméticas simples envolvendo apenas somas e produtos, a variável x, e parênteses V={a,b,S,A}, Σ={a,b}, • P={S→AA, A→AAA, A→a, A→bA, A→Ab} gera cadeias com um número de a’s par e não nulo. • V={S,(,)}, Σ={(,)}, P={S→ε , S→SS, S→ (S)} gera cadeias com um número balanceado de parênteses, escritos em ordem correta. Linguagens Regulares e Livres de Contexto Uma gramática livre de contexto G=(V,Σ,P,S) é dita regular se e só se P ⊆ (V-Σ Σ) × Σ* ((V-Σ Σ) ∪ {εε}) Prova-se que Uma linguagem é regular se e só se for gerada por uma gramática regular. Prova-se também que Qualquer linguagem sobre um alfabeto unitário é sempre uma linguagem regular. Note que não é necessário que uma linguagem gerada por gramática livre de contexto contenha aninhamentos sintáticos. (exemplifique) Note também que nem todo aninhamento sintático definido em gramática livre de contexto implica obrigatoriamente que a linguagem não seja regular. (exemplifique) Reconhecimento Linguagens livres de contexto não-regulares exigem, para seu reconhecimento, algo mais que um autômato finito. Torna-se necessária uma memória para o registro de fatos acerca da parte já lida do texto de entrada. A memória é usada para assegurar um casamento perfeito entre os delimitadores esquerdo e direito de construções sintáticas aninhadas. Não-determinismos também podem ser usados para manipular a informação memorizada durante o reconhecimento das sentenças. Um autômato para o reconhecimento estrito de linguagens livres de contexto deve ser inspirado nas gramáticas livres de contexto. Derivação mais à esquerda Para G=(V,Σ,P,S) livre de contexto, w ∈ L(G) ⇔ ∃ S G*w, ou seja, S G w1 G w2 G ... G wn-1 G w. Se wi G wi+1 sempre ocorrer por substituição do não-terminal mais à esquerda de wi, esta será chamada uma derivação mais à esquerda, L sendo denotada wi G wi+1, com wi, wi+1 ∈ V*, se e só se (1) wi=α1Aα2,wi+1=α1γα2, (2) A→γ for uma regra de G e (3) α1∈Σ*. L L *G . por Denota-se o fechamento de Kleene de G Prova-se que Para toda gramática livre de contexto G=(V,Σ,P,S), e L toda cadeia w∈Σ*, S *G w se e só se S *G w .
Exercícios 1. Projete uma gramática livre de contexto que descreva a linguagem definida pela expressão regular (a(a|b)*|c)* 2. Usando como base a gramática do exercício anterior, desenhe a árvore de sintaxe da sentença aabbabacacabc 3. Projete uma gramática livre de contexto que descreva a linguagem das expressões aritméticas simples, formadas de variáveis ou inteiros, somas, subtrações, multiplicações, divisões e potenciações, além de outras expressões entre parênteses, entre colchetes ou entre chaves. 4. Usando como base a gramática do exercício anterior, desenhe a árvore de sintaxe da sentença (1+a*4)**(3/x-2) 5. Descreva através de uma gramática livre de contexto a sintaxe de programas formados de blocos aninháveis delimitados por um par de chaves, e formados de uma seqüência opcional de declarações seguidas de seqüências de comandos, podendo os comandos ser por sua vez blocos, comandos simples ou comandos vazios. Os elementos das seqüências são separados por ponto-evírgulas. Represente um comando por c e uma declaração por d. Complete esta descrição se sentir falta de maiores detalhes para desenvolver a gramática. 6. Usando como base a gramática do exercício anterior, desenhe a árvore de sintaxe e explicite uma derivação mais à esquerda para o programa {d;d;d;c;{c;c;{d;d;c;;c;};c;c};;} 7. Defina, através de uma gramática livre de contexto, a sintaxe da notação utilizada para se descrever expressões regulares sobre um alfabeto {a,b,c}. 8. Mostre por que razão a gramática do exercício anterior define uma linguagem livre de contexto não regular. 9. Se as expressões regulares servem para definir linguagens regulares, a afirmação anterior não deveria constituir um paradoxo? 10. Usando a gramática do exercício 7, derive, por meio de derivações mais à esquerda, a expressão regular do enunciado do exercício 1. Monte também a árvore de sintaxe dessa sentença.
PCS-2427 – Lógica Computacional – Aula 14 – prof. João José Neto Assunto: Reconhecedores para Linguagens Livres de Contexto: Autômatos de Pilha Autômato de Pilha Teorema – Toda linguagem aceita por autômato de pilha é livre de contexto Notar que v e y se comportam como um par de delimitadores casados, Autômato de pilha é uma sêxtupla M=(Q,,,,q0,F), com Para M=(Q,,,,q0,F) qualquer, efetuam-se no autômato simplificações aninhando sucessivamente o centro x da cadeia w. n n n Q - conjunto de estados; - alfabeto de entrada; - alfabeto de pilha; estruturais , ou seja, transformações que eliminam consultas a mais de um Teorema - A linguagem L={a b c |n0} não é livre de contexto Prova: Seja G uma gramática livre de contexto tal que L=L(G); Seja k uma constante para elemento da pilha de cada vez, e que permitem, se necessário, a consulta ao - relação de transição: (Q * *) (Q *); n n n G, dada pelo teorema anterior; Seja n>k/3. Nessas condições, w=a b c pode ser topo da pilha sem desempilhar o elemento consultado: (i) eliminação de q0 - estado inicial; F - conjunto de estados finais F Q i i escrita na forma w=uvxyz, |v|0, |y|0, com uv xy zL(G). Isto é impossível, pois se Se ((p, u, ), (q,)) , então estando M no estado p, com no topo da transições ((q, u, ), (p, )) com ||>1; (ii) incluir em Q novos estados t1,..., tn2 2 v ou y contiver dois símbolos de {a,b,c} então uv xy z conterá obrigatoriamente um c pilha, poderá consumir u da cadeia de entrada, e evoluir para o estado q, 1; (iii) incluir em o conjunto de transições ((q, , B1), (t1, )) , ((t1, , B2), (t2, antes de um b ou um b antes de um a. Se v e y contêm cada um apenas a’s, ou 2 2 modificando para o topo da pilha. Este par ordenado é chamado transição )) , ... , ((tn-2, , Bn-1), (tn-1, )) , ((tn-1, u, Bn), (p, )) ; (iv) acrescentar transições apenas b’s ou apenas c’s, então uv xy z não poderá conter o mesmo número de a’s, b’s e c’s. ((q, u, A), (p, A)) para cada A sempre que contiver ((q, u, ), (p, )) de M. As transições podem ser aplicadas de forma não-determinística. Propriedades das linguagens livres de contexto: Serão estudados três tipos Teorema - Linguagens livres de contexto não são fechadas em relação à Funcionamento Configuiração de um autômato de pilha é um membro de Q * *, de propriedades: (i) Propriedades de fechamento; (ii) Propriedades de operação de intersecção ou de complementação das duas linguagens abaixo não é livre de contexto: caracterizando, em um dado momento, o estado, a parte não lida da cadeia periodicidade; (iii) Propriedades algorítmicas. Essas propriedades facilitam o Intersecção: A intersecção n n m m n n n n n {a b c |m,n0}{a b c |m,n0}={a b c |n0} reconhecimento de uma linguagem como sendo ou não livre de contexto, de entrada e o conteúdo da pilha, lido a partir do seu topo. Complementação: Não sendo fechadas em relação à intersecção, não serão fechadas em Para todo ((p, u, ), (q,)) , x* e *, define-se (p, ux, ) M facilitam a busca de algoritmos para responder a certas questões sobre relação à complementação, pois, pelo teorema de De Morgan, L 1L2=*-((*(q, x, ), válido entre configurações desta forma, para alguma transição, linguagens livres de contexto e proporcionam, através de suas provas, um L1)(*-L2)) maior domínio sobre a estrutura dessas linguagens. algum x e algum Teorema - Linguagens livres de contexto sobre alfabetos unitários são Propriedades de Fechamento Notação: O símbolo M* denota o fechamento de Kleene para M . sempre regulares Teorema – As linguagens livres de contexto são fechadas em relação às Prova: Se a linguagem é livre de contexto, ela pode ser representada por gramáticas livres M aceita w* se e só se (q0, w, ) M* (p, , ), com p F. p q p operações de união, concatenação e fechamento de Kleene de contexto; As produções serão da forma Na N’a ou Na , com p,q0, Neste caso, há uma seqüência c0 M c1 M ... M cn de configurações ci , p Seja G =(V , ,P ,S ), G =(V , ,P ,S ), com V - V - = ={a}, N,N’ V-Como Na a* N V- , e como NapN’aq gera as 1 1 1 1 1 2 2 2 2 2 1 1 2 2 com c0=(q0, w, ) e cn=(p, , ), p F. p+q Prova: Em cada caso, cria-se uma gramática que simule a operação desejada: mesmas cadeias que Na N’ N, N’ V-então é possível obter, a partir Esta seqüência é uma computação executada por M sobre w, e tem União: G=(V1 V2 {S} , 12, P1 P2 {SS1 , S S2}, S) desta gramática, uma gramática regular. Logo, a linguagem em questão será comprimento n (tem n passos). sempre regular Concatenação: G=(V1 V2 {S}, 12, P1 P2 {SS1 S2}, S) L(M), linguagem aceita por M, compreende todas as cadeias aceitas por M: Kleene: G=(V1 , 1, P1 {S , SS S1}, S) Propriedades Algorítmicas das linguagens livres de contexto L(M)={w*|(q0,w,) M* (p,,), pF} Teorema - A intersecção de uma linguagem livre de contexto com uma Teorema: Existem algoritmos para solucionar as seguintes questões sobre Exemplo – Palíndrome ímpar centrada linguagem regular é uma linguagem livre de contexto gramáticas livres de contexto: (i) Dada uma gramática G e uma R Para L={wcw |w{,}*}, pode-se usar o autômato com Prova: Sejam M1=(Q1,1,1,1,q01,F1) e M2=(Q2,2,2,q02,F2) os autômatos que cadeia w, w L(G)? (ii) L(G)= ? = {
((q0,,), (q0,)), ((q0,c,), (f,)), ((f,,), (f,)),
((q0,,), (q0,)), ((f,,), (f,)) }
Exemplo – Para L={w{,}*|w contém o mesmo número de ’s e ’s} = {
((q0,,), (q1,c)), ((q1,,), (q1,)), ((q1,,c), (q1,c)), ((q1,,), (q1,)),
((q1,,c), (q1,c)), ((q1,,), (q1,)), ((q1,,), (q1,)), ((q1,,c), (f,))
}
Exemplo – Palíndrome par (Observar o não-determinismo neste autômato!) Para L={wwR|w{,}*}, pode-se usar o autômato com = {
((q0,,), (f,)), ((q0,,), (q0,)), ((f,,), (f,)),
((q0,,), (q0,)), ((f,,), (f,))
}
Teorema - Se M é um autômato de pilha e (q1, w1, 1) M* (q2, , 2) e (q2, w2, 23) M* (q3, , 4), então (q1, w1w2, 13) M* (q3, , 4).. (Divide-se o reconhecimento em duas etapas; em q2, a pilha não está vazia) Corolário – Nas condições do teorema anterior, se ocorrer (q1, w1, 1) M* (q2, , ) e (q2, w2, 3) M* (q3, , ), então (q1, w1w2, 13) M* (q3, , ).. (caso particular: 2=4=. Pilha vazia: separam-se os dois reconhecimentos) Teorema – Toda linguagem livre de contexto é aceita por autômato de pilha Prova: a partir de uma gramática livre de contexto G=(V,,P,S) da linguagem desejada, constrói-se M=(Q,,,,q0,F) tal que L(M)=L(G): Faz-se Q={p,q}; q0=p; F={q}, e constrói-se assim: ={ ((p, , ), (q, S)) } { ((q, , A), (q, x)) | A x P } { ((q, a, a), (q, ) | a }
empilhaS substitui não-terminais desempilha terminais
Por indução, prova-se que este autômato simula derivações mais à esquerda.
representam respectivamente as linguagens livre de contexto e regular. Prova: Pode-se determinar se w L(G) verificando se w é contorno de alguma das Combinam-se os dois autômatos em um único, M, que efetue em paralelo o árvores, de altura máxima |w|. Eliminam-se da gramática todas as regras dos reconhecimento das duas linguagens, aceitando a cadeia apenas se ambos os tipos Ae AB. Por inspeção exaustiva (finita) de árvores de altura máxima autômatos a aceitarem: M=(Q1Q2,,1,,(q01,q02),F1F2), com dado por: |V-| é sempre possível determinar se L(G)= (((q1,q2),u,) , ((p1,p2),)) se e só se ((q1,u,) , (p1,)) 1 e (q2,u) M2* Autômatos de Pilha Determinísticos (p2,)
Árvore de Derivação de uma cadeia por uma gramática É uma representação gráfica da derivação desta cadeia. A raiz da árvore corresponde à raiz da gramática; Os nós da árvore correspondem aos nãoterminais; As folhas da árvore correspondem aos terminais. Para uma gramática livre de contexto G=(V,,P,S) tem-se as seguintes leis de formação de árvores de derivação: a cadeia vazia é representada como uma árvore elementar, assim como um símbolo terminal; um não-terminal é o nó principal de uma sub-árvore, cujos ramos representam os componentes do lado direito de uma produção referente àquele não-terminal, os quais podem ser, por sua vez, terminais, não-terminais ou a cadeia vazia. Um caminho em uma árvore de derivação é uma seqüência de nós distintos, cada qual conectado ao anterior por um só segmento, sendo o primeiro nó do caminho a raiz da gramática, e o último nó, uma folha da árvore de derivação. O comprimento de um caminho é o número de seus segmentos. A altura de uma árvore de derivação é o comprimento do seu caminho mais longo. Propriedades de Periodicidade das linguagens livres de contexto Teorema do Bombeamento - Para gramática cada G livre de contexto há um k tal que qualquer cadeia w em L(G), com |w|>k, pode ser decomposta como w=uvxyz, com |v|0 , |y|0. Nessas condições, uvnxynz também deverá estar em L(G), para todo n 0.
Um autômato de pilha M é dito determinístico se, sempre que M estiver na configuração (p,w,) e para os prefixos w1 e w2 de w e 1 e 2 de , tanto ((p,w1,1),(q1,1)) como ((p,w2,2),(q2,2)) são transições de M, então estas transições deverão se iguais: w1=w2, 1=2, 1=2. Equivalentemente: Duas cadeias são consistentes se uma delas for prefixo da outra; duas transições são compatíveis se partirem do mesmo estado, se suas cadeias de entrada forem consistentes e se as correspondentes cadeias de pilha também o forem; M é determinístico se não tiver transições compatíveis Linguagens livres de contexto determinísticas São as que podem ser aceitas por algum autômato de pilha determinístico. Por questões práticas, e sem perda de generalidade, será exigido que uma cadeia de entrada sempre seja finalizada por um símbolo indicador de final de cadeia, para que a cadeia possa ser reconhecida com mais facilidade. Teorema – L* é uma linguagem livre de contexto determinística se, para algum autômato de pilha determinístico M, tem-se que L = L(M). Teorema – Toda linguagem livre de contexto determinística é também uma linguagem livre de contexto. Teorema – Seja L* uma linguagem livre de contexto tal que, para cada u* existe um v* tal que u°vL, e *-L não é livre de contexto. Nessas condições, a linguagem L não é livre de contexto determinística. Exemplo: L0={ am1bam2bam3b...bamn | mi,mj0, mimj para algum i,j }
PCS-2427 – Lógica Computacional – Aula 15 – Prof. João José Neto Assunto: Linguagens e Gramáticas Sensíveis ao Contexto Autômatos não são as únicas formas de implementação de computações: Há gramáticas gerais, equivalentes às máquinas de Turing. Gramáticas irrestritas (1) • São dispositivos de geração de linguagens • São sistemas de transcrição • Nas gramáticas irrestritas, o lado esquerdo das regras não se restringe apenas a um não-terminal isolado Gramáticas Irrestritas são quádruplas: G=(V,,P,S) V = alfabeto da gramática = conjunto de terminais V N = conjunto de não-terminais N = V- S = símbolo de partida (raiz da gramática) SN P = o conjunto de regras de substituição (produções) deve ser um subconjunto finito de (V*NV*)V* • Regras são denotadas: u G v para todo (u,v)P se e só se, para algum w1, w2 V* e alguma regra • u G v u’ G v’, tem-se: u = w1 u’ w2 e v = w1 v’ w2 • G* denota o fechamento de Kleene para o operador G • w* é gerada por G se e só se S G* w • L(G) é o conjunto de todas as cadeias de * geradas por G • w0 G w1 G ... G wn é uma derivação • Restringindo-se as gramáticas gerais, é possível definir gramáticas livres de contexto impondo que uN, o que elimina as substituições condicionais • Restringindo-as ainda mais, de modo que v*(N{}) ou v(N{})*, são obtidas as gramáticas lineares fatoradas à esquerda ou fatoradas à direita, respectivamente • Gramáticas lineares geram cadeias acrescendo terminais a uma só das extremidades da forma sentencial
Exemplo (1) • Uma gramática que gera apenas sentenças sobre {a,b,c} com igual ocorrência de cada um dos símbolos. 1. S 2. S ABCS [ 1-2 gera (ABC) n , n 0 ] 3. AB BA 4. BA AB 5. AC CA 6. CA AC 7. BC CB 8. CB BC [ gera todos os anagramas ] 9. A a 10. B b 11. C c [ elimina os não terminais ] Exemplo (2) n
• Gramática que gera a linguagem { a2 | n 0 } 1. 2. 3. 4. 5. 6. 7.
S [A] [ [D DA AAD D] ] [ ] A a
[ gera um só A entre colchetes ] [ cria certo número n de D’s ] [ D duplica cada A que salta ] [ na extremidade, D é eliminado] [elimina os ... ... colchetes] [ elimina os não terminais ]
Exercícios: Construir gramáticas irrestritas para as linguagens seguintes: 1. { wcw | w { a, b }* } 2. { wwRw | wR é a cadeia reversa de w { a, b }* } 3. { anbncn | n > 0} 4. { anbmcndm | m, n > 0 } 5. { aibjck | i 0 } 7. { w (wR)2 | wR é a cadeia reversa de w { a, b }* }
PCS-2427 - Lógica Computacional – Aula 16 – prof. João José Neto Assunto: Máquina de Turing
( . %9
0 ∈ 9
5: ' " #
$
% S
a
b
b
...
a
? h
q0
q3
7
4
'
()* +, '
: ∈ Σ ∪ =; < >
;
,6 (
: ,
-
A
'
2
!$ +,
@
8 8
,
' '
%
$
'
0
4 0 (
E
A
E
%G
-
%
5
E
8
8 ( F A E,
F
-
: D !$
E
F
E
.
8 6 (9 Σ δ , % (9 ∪ =5 >, × Σ@ × Σ × ((Σ@(Σ $ =* >,, ∪ =ε>, 2 $ ! ( A , 5 8 BC
4
D
-
'
.
(
,
F
8
δ
()5
3'
6 (
#
,
-
1
E,
E
!
8
@
F
8 H
,
F
BC
'
/
2
A F F F, ∈ (Σ ∪ =; < >, δ( % : E6 F F6
<
$
7
δ( '
'
'
(5 6 5
∈Σ
'
?
0
• • •
:
(5 ,
. !
σ
(
$
4
-
(
8
0
&
E,
E
∈Σ A E6 A F 6 ; A E6 A F F , F6 E E E≠* E ≠ ε: , F6 ε E6 * E 6 ε: 6 < A F6 A E E , E 6 F F: , F6 ε E6 ε F6 *:
%
.
q1
q2
' σ$2 < $8 ; $8 ∈9
• • • 4
E
: Σ ' ; <: (9 ∪ =5 >, × (Σ ∪ =; < >,
(* , 9 ×Σ
δ
!
A
E
86 (9 Σ δ ,
8
E
BC ≥H
F
BC
%
H
8
E
8
F
8
8
!$ -
$
; A #-
I C
8
F,
F
%
8 6 (9 Σ δ , 8
0
!
1 EO P Q < FHHO
) I 2
+
J F FHHL
K
% !"
# %. M
R
I
IJ
K
! N
PCS-2427 - Lógica Computacional – Aula 17 – prof. João José Neto Assunto: Computação com Máquina de Turing Computação com Máquina de Turing Convenção – formato convencionado para os dados de entrada de uma máquina de Turing: A cadeia de símbolos deverá estar entre dois brancos; Deve estar ajustada à extremidade esquerda da fita; O cabeçote deve apontar o branco que segue os dados; A máquina deve estar posicionada em seu estado inicial. Def.: Função sobre cadeias, computável por máquina de Turing. Sejam 0 e 1 alfabetos que não contêm o símbolo #. Seja uma função de 0* para 1*. Uma máquina de Turing M = (Q, , , s) é capaz de computar se 0, 1 , e para qualquer 0*, se () = 1*, então (s,##) ┣M * (h,# #). Se existe alguma máquina de Turing nessas condições, então a função é dita Turing-computável. Convenção - A definição estabelece também uma convenção para a saída da computação. Por compatibilidade com a convenção para a cadeia de entrada, deve haver um # à esquerda da cadeia de saída, e após a computação o cabeçote deve estar posicionado sobre um #, imediatamente à direita de . Caso tenha mais de um parâmetro, trata-se a seqüência como se fosse um só bloco, separando-se os argumentos por um #. Dessa forma, caso ( 1, 2, ..., n ) = , então ( s, #1#2#...#n# ) ┣M * ( h, ## ). Funções Numéricas Turing-Computáveis Se : N N, usa-se um alfabeto unitário { I }, e Ik representa o número k. M = (Q, , , s) computa se e somente se M computar ’: {I}* {I}* e ’(In) = I(n), para cada n N. Dizse neste caso que é Turing-computável. Linguagens Turing-Decidíveis Linguagens Turing-decidíveis são as que contam com alguma máquina de Turing que decida se uma entrada qualquer pertence ou não à linguagem. Seja 0 um alfabeto que não contenha #. Sejam Y e N dois símbolos não presentes em 0.
Então a linguagem L 0* é Turing-decidível se e somente se a função L : 0* {Y, N} é Turing-computável, desde que, para cada 0*: L() = Y se L, L() = N se L Se L for computada por alguma máquina de Turing M, diz-se que M decide L, ou que M constitui um procedimento de decisão para L. Construção de aceitadores. Diz-se que uma máquina de Turing M aceita uma cadeia L (Linguagem especifíca), se M pára (“halt”) com a entrada . Então, seja 0 o alfabeto gerador de L, e L 0*, M aceita L se e somente se L = { 0* : M aceita }, e uma linguagem é dita Turing-aceitável se há uma máquina de Turing que a aceita. É fácil constatar que toda linguagem Turing-decidível é também Turing-aceitável, porém o inverso não é verdade. Lema: Seja M uma máquina de Turing tendo (qi, iaiui) como configurações de M, para i = 1, 2, 3,. Se (q1, 1a1u1) ┣M * (q2, 2a2u2), e (q2, 2a2u2) ┣M * (q3, 3a3u3), então: (q1, 1a1u1) ┣M * (q3, 3a3u3). Combinação de Máquinas de Turing Def.: Um esquema de máquina de Turing é uma tripla (M, , M0), no qual M é um conjunto finito de máquinas de Turing com um alfabeto comum e conjuntos distintos de estados. M0 M é a máquina inicial; é uma função parcial, de um subconjunto de M para M. Def.: Seja M = (M0, ..., Mn), com n 0, com Mi = (Qi, , i, si) para i= 0, ..., n. Sejam q0, ..., qm novos estados não contidos em Qi. Então se (M, , M) é um esquema de máquina de Turing, diz-se que este é representativo da máquina de Turing M = (Q, , , s), na qual: Q = Q0 Q1 ... Qn {q0, ..., qm}; s= s0; é definido como: 1) Se 0 i m, q Qi, a , e i(q, a) = (p, b), em que ph, então (q, a) = i(q, a) = (p, b); 2) Se 0 i m, q Qi, a , e i(q, a) = (h, b), então (q, a) = (qi, b); 3) Se 0 i m, q Qi, a , e (Mi, a) não é definida, então (qi, a) = (h, a);
4) Se 0 i m, q Qi, a , e (Mi, a) = Mj, e seja j(sj, a) = (p, b), então: (qi, a) = (p, b) se ph, e (qi, a) = (qj, b) se p=h É possível construir um conjunto de máquinas que seguem essas convenções, formando uma biblioteca de blocos funcionais (R, L, Rn, Ln, R#, L#, , ...) cujas instâncias podem ser combinadas para formarem máquinas de Turing mais complexas. Extensões Possíveis para Máquinas de Turing Algumas extensões para a máquina de Turing foram propostas no sentido de ampliar sua capacidade computacional, entretanto pouco ou nenhum resultado considerável foi obtido neste campo, assim tem-se: 1) Fita infinita à esquerda e à direita. 2) Múltiplas fitas. 3) Múltiplas fitas e múltiplas cabeças independentes de leitura e gravação. 4) Máquina de Turing não-determinística Teorema: Qualquer uma dessas máquinas de Turing estendidas pode ser reduzida ao caso clássico estudado. Teorema: Qualquer problema que pode ser resolvido por uma máquina de Turing não-determinística também pode ser resolvido por uma máquina de Turing determinística.
Material de Apoio para esta aula: Lewis e Papadimitriou – Elements of the theory of computation. Existe a tradução para o português, da Bookman, Porto Alegre: Elementos de teoria da computação, 2a. edição. CUIDADO: Utilizar apenas a “versão totalmente revisada”, de 2004. Harrison – Introduction to formal language theory – Addison Wesley, 1978. Ramos, Neto e Vega – Linguagens Formais – Bookman, Porto Alegre, 2009.
PCS-2427 – Lógica Computacional – Aula 18 – Prof. João José Neto Assunto: Linguagens Recursivas e Recursivamente Enumeráveis. Gramáticas Irrestritas Máquinas de Turing podem definir uma linguagem quando, para qualquer cadeia dada, a máquina parar em um de dois tipos de estados de parada: num estado de aceitação, caso a cadeia pertença à linguagem, ou em um estado de rejeição, em caso contrário [a máquina decide a linguagem]. Ao conjunto de linguagens assim definidas dá-se o nome de linguagens recursivas. Uma linguagem é dita recursiva quando existir alguma máquina de Turing que a decida. Exemplo: Uma máquina de Turing que, para toda entrada formada de n caracteres I (n≥0), pára com uma cadeia de n+1 caracteres I na fita Ainda usando máquinas de Turing, é possível definir uma linguagem da seguinte maneira alternativa: dada uma cadeia, diz-se que, se ela pertence a essa linguagem, a máquina de Turing parará em resposta a essa cadeia, e, caso a cadeia não pertença à linguagem, a máquina não parará, independente do conteúdo da fita [a máquina semi-decide a linguagem]. As linguagens assim definidas formam a classe das linguagens recursivamente enumeráveis.. Uma linguagem é dita recursivamente enumerável quando existir alguma máquina de Turing que a semi-decida. Exemplo: Uma máquina de Turing que, para toda entrada formada de caracteres a e b, pára somente ao encontrar o primeiro caractere a na fita, aceitando portanto apenas cadeias que contenham algum a. Note-se que, ao contrário do caso das linguagens recursivas, essas máquinas de Turing, que não terminam sua operação quando a cadeia de entrada não pertencer à linguagem que definem, não constituem algoritmos e portanto não são úteis para classificar cadeias, pois entram em loop infinito para certas cadeias. Teorema 1 – Toda linguagem recursiva é recursivamente enumerável, mas nem toda linguagem recursivamente enumerável é recursiva. Teorema 2 – O complemento de toda linguagem recursiva é uma linguagem recursiva (linguagens recursivas são fechadas em relação à complementação). Teorema 3 – Linguagens recursivamente enumeráveis não são fechadas em relação à complementação.
Outra maneira de definir linguagens recursivamente enumeráveis é através de dispositivos geradores denominados Gramáticas Irrestritas, também chamados sistemas de reescrita ou de regravação. Ver mais detalhes na aula 15. Teorema 3 – Uma linguagem pode ser gerada por uma gramática irrestrita se e somente se ela for recursivamente enumerável. Teorema 4 – Toda gramática pode ser convertida em uma gramática equivalente cujas regras sejam todas da forma uAv→ →uwv, com A não-terminal, e u, v, w cadeias arbitrárias de terminais e/ou não-terminais.
Exercícios 1. Construa uma máquina de Turing capaz de decidir as seguintes linguagens sobre {a,b}: a) ∅ b){ε} c){a} d) {a}* 2. Construa uma máquina de Turing capaz de semi-decidir a seguinte linguagem regular: a*ba*b. 3. Prove que as linguagens recursivas são fechadas em relação às operações de concatenação, união e fechamento de Kleene. 4. Prove que as linguagens recursivamente enumeráveis são fechadas em relação às operações de concatenação, união e fechamento de Kleene. 5. Dada uma gramática irrestrita com as seguintes produções: S→ ABCS S→Tc CA→AC BA→AB CB→BC BTb→Tab ATa→Taa CTc→Tcc CTc→Tbc BTb→Tbb Ta→ε Pede-se determinar qual é a linguagem gerada pela gramática e derivar, passo a passo, uma sentença de comprimento maior ou igual a 7. Desenhar o grafo de derivação desta sentença.
PCS-2427 – Lógica Computacional – Aula 19 – Prof. João José Neto Assunto: Uma forma normalizada para as gramáticas irrestritas e dependentes de contexto
Teorema - Qualquer gramática pode ser convertida em uma gramática
R2 CA → R2 A R3 BA→ → R3 A R4 CB → R4 B R5 C Tc → R5 Tc R6 C Tc → R6 Tc R7 B T b → R7 T b R8 B T b → R8 T b R9 A T a → R9 T a
R2 A → R2 R3 A → R3 R4 B → R4 R 5 T c → R5 R 6 T c → R6 R 7 T b → R7 R 8 T b → R8 R 9 T a → R9
R2 → AC R3 → AB R4 → BC R5 → Tc Z R6 → Tb Z R7 → T b Y R8 → T a Y R9 → Ta X
( 1) S → Tc ( 2.2) R2 CA → R2 A ( 3.2) R3 BA→ → R3 A ( 4.2) R4 CB → R4 B ( 5.2) R5 C Tc → R5 Tc ( 6.2) R6 C Tc → R6 Tc ( 7.2) R7 B Tb → R7 Tb ( 8.2) R8 B Tb → R8 Tb ( 9.2) R9 A Ta → R9 Ta (11) X → a
( 2.3) R2 A → R2 ( 2.4) R2 → AC ( 3.3) R3 A → R3 ( 3.4) R3 → AB ( 4.3) R4 B → R4 ( 4.4) R4 → BC ( 5.3) R5 Tc → R5 ( 5.4) R5 → Tc Z ( 6.3) R6 Tc → R6 ( 6.4) R6 → Tb Z ( 7.3) R7 Tb → R7 ( 7.4) R7 → Tb Y ( 8.3) R8 Tb → R8 ( 8.4) R8 → Ta Y ( 9.3) R9 Ta → R9 ( 9.4) R9 → Ta X (12) Y → b (13) Z → c
Exercícios
4. 5.
∩ !
∪
}
∈
∈
6.
L3 = {
3.
2.
Construir gramáticas para as linguagens abaixo indicadas, e normalizá-las, de acordo com o método utilizado na demonstração do teorema: 1. ∈
para cada terminal (a, b ou c) • acrescentar um novo não-terminal correspondente (X, Y ou Z), substituindo a por X, b por Y e c por Z em todas as suas ocorrências na gramática. • acrescentar as regras X → a, Y → b, Z → c Resulta: ( 2) CA → AC ( 3) BA → AB ( 0) S → ABCS ( 1) S → Tc ( 4) CB → BC ( 5) C Tc → Tc Z ( 6) C Tc → Tb Z ( 7) B Tb → Tb Y ( 8) B Tb → Ta Y ( 9) A Ta → Ta X (10) Ta → ε (11) X → a (12) Y → b (13) Z → c • substituir cada uma das regras da forma A1A2...An → wk onde n > 1 (regras 2,3,4,5,6,7,8,9): A1A2...An → Rk A1A2 ... An (em que A1 foi substituído por RkA1) Rk Ai Ai+1...An→ Rk Ai+1 ... An para cada i ≤ n, ( de forma que Ai seja eliminado [correspondente a Ai → ε ] ) Rk → w k • substituir regras do tipo KL→ → wk por {KL → Rk KL, Rk K L → Rk L, Rk L → Rk, Rk → wk}
!
•
( 0) S → ABCS ( 2.1) CA → R2 CA ( 3.1) BA → R3 BA ( 4.1) CB → R4 CB ( 5.1) C Tc → R5 C Tc ( 6.1) C Tc → R6 C Tc ( 7.1) B Tb → R7 B Tb ( 8.1) B Tb → R8 B Tb ( 9.1) A Ta → R9 A Ta (10) Ta → ε
n n n
Vamos aplicar o método apresentado à gramática seguinte, que gera a b c , n >1: ( 2) CA → AC ( 3) BA → AB ( 0) S → ABCS ( 1) S → Tc ( 4) CB → BC ( 5) CTc → Tc c ( 6) CTc → Tb c ( 7) BTb → Tb b ( 8) B Tb → Ta b ( 9) A Ta → Ta a (10) Ta → ε
CA → R2 CA BA → R3 BA CB → R4 CB C T c → R5 C T c C T c → R6 C T c B T b → R7 B T b B T b → R8 B T b A T a → R9 A T a
por por por por por por por por
A gramática assim obtida é equivalente à inicial, mas suas regras são todas da forma normalizada u N v → u w v especificada pelo teorema:
"
Exemplo
( 0) S → ABCS ( 1) S → Tc ( 2) CA → AC ( 3) BA → AB ( 4) CB → BC ( 5) C Tc → Tc Z ( 6) C Tc → Tb Z ( 7) B Tb → Tb Y ( 8) B Tb → Ta Y ( 9) A Ta → Ta X (10) Ta → ε (11) X → a (12) Y → b (13) Z → c
equivalente em que todas as produções são da forma uNv→uwv com N não-terminal, u e v cadeias arbitrárias envolvendo terminais e/ou não-terminais • para cada terminal a, – acrescentar um novo não-terminal correspondente A, substituindo a por A em todas as suas ocorrências na gramática – acrescentar a regra A → a • remover cada regra da forma A1A2...An → wk onde n > 1, ( notar que, nessas condições, todo Ai será um não-terminal e todo wk será uma cadeia envolvendo apenas não-terminais ) • no lugar de cada regra removida no passo anterior, acrescentar as seguintes regras: A1A2...An → Rk A1A2 ... An (em que A1 foi substituído por RkA1) Rk Ai Ai+1...An→ Rk Ai+1 ... An para cada i ≤ n, de forma que Ai seja eliminado [correspondente a Ai → ε ] Rk → w k • manter intactas as demais produções da gramática original. A gramática assim obtida é equivalente à inicial, mas suas regras são todas da forma u N v → u w v especificada no enunciado
PCS-2427 – Lógica Computacional – Aula 20 – Prof. João José Neto Assunto: Equivalências entre os dispositivos gramaticais e os autômatos estudados (fonte: Ramos, Neto e Vega Linguagens formais, cap.7) algoritmo, representado pela máquina de Turing que decide a linguagem em questão. 1. Linguagens regulares Exemplo: L7={ αi | αi ∉ L(Gi), ∀i ≥1 } Linguagens regulares são construídas aplicando-se apenas concatenações, uniões e estrelas de Kleene sobre os elementos de seu alfabeto. Linguagens regulares são Toda gramática dependente de contexto pode ser convertida à forma normal na qual aceitas por autômatos finitos não-determinísticos. Linguagens regulares são aceitas todas as regras de substituição promovem a reescrita de um não-terminal dentro de por autômatos finitos determinísticos. Linguagens regulares são representadas por um contexto explicitamente especificado. As linguagens dependentes de contexto expressões regulares. Linguagens regulares são geradas por gramáticas lineares (à englobam todas as anteriores – regulares e livres de contexto, que são seus casos direita / à esquerda). Exemplo: L1={ w∈ ∈{a,b}* | w=a*b* } particulares. 5. Linguagens recursivamente enumeráveis 2. Linguagens livres de contexto Linguagens livres de contexto são construídas aplicando-se, além das concatenações, Máquinas de Turing que semi-decidem linguagens representam a classe das linguagens uniões e estrelas de Kleene, também aninhamentos sintáticos sobre os elementos de recursivamente enumeráveis. Gramáticas irrestritas também representam as seu alfabeto. As linguagens livres de contexto englobam as regulares, que são seus linguagens recursivamente enumeráveis. Exemplo: L8 = { C(M)w ∈ Σ * | w ∈ L(M) } casos particulares Toda gramática irrestrita pode também ser convertida à forma normal na qual todas as Linguagens livres de contexto que não apresentam aninhamentos sintáticos são regras de substituição promovem a reescrita de um não-terminal dentro de um também linguagens regulares. Linguagens livres de contexto são aceitas por contexto explicitamente especificado. As linguagens recursivamente enumeráveis são autômatos de pilha. Em particular, são aceitas também por autômatos de pilha as mais gerais, e por isso englobam todas as demais. estruturados. Há autômatos de pilha estruturados em que os aninhamentos sintáticos 6. Linguagens estruturadas em frases se expressam na forma de chamadas auto-recursivas de sub-máquinas. Linguagens livres de contexto são representadas por expressões regulares estendidas, que Todas as linguagens sobre o alfabeto Σ , inclusive as que não se enquadram em nenhum dos casos anteriores, formam a classe de linguagens estruturadas em frases, e não permitem o uso de não-terminais para representarem expressões completas (uma das são representáveis nem por gramáticas irrestritas nem por máquinas de Turing. notações usuais é a Notação de Wirth). Linguagens estruturadas em frase que não são recursivamente enumeráveis são Linguagens livres de contexto determinísticas são aceitas por autômatos de pilha chamadas linguagens não-gramaticais. Exemplo: L9 = { C(M)w∈ ∈Σ * | w ∉ L(M) } determinísticos. Linguagens livres de contexto determinísticas são geradas por gramáticas livres de contexto LL(k) ou LR(k). As linguagens representáveis por gramáticas LL(k) também o são por gramáticas LR(k), mas o oposto não ocorre. Há Exercícios linguagens livres de contexto que não são LL(k) nem LR(k), e formam a classe das 1. Exemplificar, usando algumas linguagens regulares à escolha, cada uma das linguagens livres de contexto intrinsecamente não-determinísticas. possibilidades de representação acima enumeradas: a construção do conjunto Gramáticas LL(k) produzem reconhecedores determinísticos descendentes (top-down). usando os três operadores básicos, os dois tipos de autômatos finitos, as expressões ∈{a,b}* | w=anbn , n>0 } Exemplo: L2={ w∈ regulares e os dois tipos de gramáticas lineares. Gramáticas LR(k) produzem reconhecedores determinísticos ascendentes (bottom-up). 2. Estabelecer alguns mapeamentos entre as representações possíveis das linguagens regulares: (a) entre expressões regulares e autômatos finitos; (b) entre autômatos ≥ 0 } ∪ { w∈ ∈{a,b,e,o}* | w=a2n+1b2n1o, n≥ ≥0 } ∈{a,b,e,o}* | w=a2nb2ne, n≥ Exemplo: L3={ w∈ finitos e gramáticas lineares; (c) entre gramáticas lineares e autômatos finitos. Linguagens livres de contexto não-ambíguas são aquelas que podem ser representadas R 3. Escolher uma linguagem livre de contexto não muito complexa e representá-la nas por gramáticas não-ambíguas. Exemplo: L4={ ww | w=∈ ∈{a,b}* } diversas formas acima mencionadas. Identificar, em cada tipo de representação, a As demais são linguagens ambíguas, que não podem ser representadas por gramáticas maneira como são representadas as concatenações, as uniões, as estrelas de Kleene, m m n n n m m n ≥ 1 } ∪ { a b a b | m,n≥ ≥1 } não-ambíguas. Exemplo: L5={ a b a b | m,n≥ os aninhamentos sintáticos. 3. Linguagens sensíveis ao contexto 4. Estabelecer ao menos uma forma sistemática de mapeamento de uma gramática livre As linguagens sensíveis ao contexto englobam as anteriores, mas não podem ser de contexto para um autômato de pilha. Aplicar para uma linguagem livre de contexto representadas por autômatos de pilha, e podem ser decididas por máquinas de Turing a sua escolha. m m m com fita limitada. Exemplo: L6={ a b c | m≥ ≥1 } 5. Escolha uma linguagem dependente de contexto que não seja livre de contexto. 4. Linguagens recursivas Represente-a usando notação de conjuntos, usando uma gramática dependente de contexto qualquer, e depois outra na forma normalizada. Represente-a também Máquinas de Turing que decidem linguagens representam a classe das linguagens usando uma máquina de Turing. recursivas. Gramáticas dependentes de contexto também representam linguagens recursivas. Todas as linguagens recursivas também podem ser aceitas por algum 6. Repita o exercício anterior para uma linguagem irrestrita à sua escolha que não seja dependente de contexto.
PCS-2427 - Lógica Computacional – Aula 21 – prof. João José Neto Assunto: A Tese de Church e Máquinas de Turing Universais A máquina de Turing não tem o seu poder computacional ampliado através de qualquer alteração estrutural. Em outros termos, tornar a fita duplamente infinita, aumentar o número de fitas, de cabeçotes, criar uma máquina de Turing não-determinística, nada aumenta o poder computacional da máquina de Turing conforme foi concebida. Existem diversos modelos computacionais distintos, como: Máquina de Turing, Máquina de Post, Funções recursivas, Cálculo-λ, e demonstra-se que são todos equivalentes em seu poder computacional. A Tese (Conjectura) de Church presume que os possíveis modelos de computação sejam todos equivalentes (não apenas os já vistos): “As máquinas de Turing são versões formais de algoritmos, e assim sendo, nenhum procedimento computacional será considerado um algoritmo se não puder ser representado como máquina de Turing.” Quando se utiliza a Tese de Church, e isso é usual em computação, pode-se demonstrar a equivalência entre um modelo computacional qualquer e a máquina de Turing apenas simulando no modelo a máquina de Turing, sem demonstrar o inverso. Computação por Gramáticas Pode-se utilizar gramáticas como dispositivos geradores de linguagens, mas também como dispositivos computacionais. Desta maneira, as gramáticas podem ser vistas como computadores de funções, desde que tais funções sejam de cadeias para cadeias. Para isso, pode-se usar a Tese de Church. Lema: Seja M=(K, Σ, δ, s) uma máquina de Turing qualquer. Então existe uma gramática G tal que para quaisquer configurações (q, u, a, v), (q’, u’, a’, v’) de M, (q, u, a, v) M* (q’, u’, a’, v’) ⇔ [uqav] G* [u’q’a’v’]. { ], [ } ∩ K ∪ Σ=∅; K ∩Σ=∅ Demonstra-se representando cada configuração como uma cadeia de símbolos, na qual o estado é um não-terminal de G, e aponta à sua direita o símbolo seguinte da cadeia. Os símbolos [ e ] inseridos servem para delimitar a cadeia de entrada: à direita de ] só há símbolos “#”. As produções
assim obtidas simulam cada movimento da máquina de Turing na gramática G=(K∪{[,],h,S}, Σ, P, S). Funções Computáveis por Gramática Com este Lema pode-se definir função gramaticamente computável: Def.: Sejam Σ0 e Σ1 alfabetos que não contêm #, e seja ƒ uma função de Σ0* para Σ1*. Então ƒ será computável por gramática se e somente se houver uma gramática G=(V,T,P,S), onde Σ0, Σ1 ⊆ T, e houver cadeias x, y, x’, y’ ∈ (V ∪ T)*, tais que para qualquer u ∈ Σ0*, v ∈ Σ1*, * ƒ(u)=v ⇔ xuy G x’vy’. A definição para funções numéricas é semelhante à da Máquina de Turing. Observa-se que x, y, x’, y’ são marcadores associados à gramática G, assim a computação só terá efeito na região delimitada pelos marcadores. Teorema: As Funções Turing-computáveis são gramaticalmente computáveis. Demonstra-se a partir de uma máquina de Turing qualquer M=(K, Σ, δ, s), para a qual ƒ(u)=v ⇔ (s,#u#) M* (h,#v#). Aplica-se o Lema anterior para obter G, e faz-se x=x’= “[#”, y=“s#]”, y’=“h#]”. Funções µ-Recursivas (não serão detalhadas aqui) Definem-se as funções recursivas primitivas e, a partir destas e de minimização ilimitada sobre funções regulares de Kleene, definem-se as funções µ-recursivas. Faz-se um paralelo com cálculo-λ, fundamento de linguagens funcionais, tais como Lisp e Scheme. Máquinas de Turing Universais Pode-se definir uma codificação padrão para um alfabeto infinito enumerável e um conjunto infinito enumerável de estados, em termos de qi h L R ai σ cadeias de símbolos. i+1 I I I2 Ii+2 λ(σ σ) I Aceita-se, dessa forma, que qualquer máquina de Turing possa ter seus estados e símbolos codificados dentro do padrão. Assim tem-se os conjuntos K = {q1, q2, ...} e Σ = {a1, a2, ...}, de tal maneira que para toda máquina de Turing o conjunto de estados seja um subconjunto finito de
K , e o alfabeto da fita seja um subconjunto finito de Σ . Adota-se a seguinte correspondência entre os símbolos usados na máquina de Turing e cadeias sobre o alfabeto unitário {I}. Esta escolha impede que haja no mesmo conjunto dois elementos igualmente representados. Usa-se um outro símbolo (“c”) para configurar a completamente a máquina. Assim, o alfabeto de representação será {c, I}. Portanto, cada símbolo e cada estado de uma máquina de Turing M=(K, Σ, δ, s) podem ser representados, e cada elemento da função de transição de uma máquina de Turing também o pode, da seguinte maneira: seja δ(q, a)=(p, b), onde q e p ∈ K ∪ {h}, a ∈ Σ , e b ∈ Σ ∪ {L, R}, então cada elemento será representado por k. cadeias Spr=“cw1cw2cw3cw4c”, (1≤p≤k, 1≤r≤ ) onde w1=λ(q), w2=λ(a), w3=λ(p) e w4=λ(b). Faça-se S0=λ(s) e defina-se a função de codificação ρ(M)=cS0cS11S12 ... Sk c. A máquina de Turing Universal opera sobre o alfabeto {c, I, #}, e recebe em sua fita a codificação ρ(M) seguida da codificação ρ(w). A operação da máquina de Turing Universal então é bastante simples, simula a execução de M a partir de s, acompanhando a função de transição e o símbolo encontrado na fita. Observe-se que mesmo que w contenha símbolos #, ρ(w) não possui #. Def.: Define-se a máquina de Turing Universal U assim: U=(KU, ΣU, δU, sU), tal que para toda máquina de Turing M=(K, Σ, δ, s) e para toda cadeia w ∈ Σ*, (i) Se (h, uav) é uma configuração de parada de M tal que (s, #w#) M* (h, uav), então (sU, #ρ(M)ρ(w)#) U* (h, #ρ(uav)#); (ii) Se (sU, #ρ(M)ρ(w)#) U* (h, u’a’v’) é uma configuração de parada de U, então a’=#, v’=ε, u’=#ρ(uav), para algum u, a, v tais que (h, uav) seja uma configuração de parada de M, e que (s, #w#) M* (h, uav). Esta máquina define o padrão usual de computação. Todo dispositivo computacional pode ser representado por uma máquina de Turing Universal, e cada máquina de Turing construída representa um algoritmo, ou seja, um programa para a máquina Universal.
PCS-2427 - Lógica Computacional – Aula 22 – prof. João José Neto
Assunto: Computabilidade e Decidibilidade – Problema da Parada da Máquina de Turing Problemas que máquinas de Turing não representam também não se resolvem algoritmicamente (tese de Church). Isso motiva a investigar problemas computáveis, chegando a importantes conclusões a partir do conceito de decidibilidade para máquinas de Turing . Teorema: Qualquer linguagem Turing-decidível também é uma linguagem Turing-aceitável. Monta-se uma máquina de Turing de aceitação, a partir da sua máquina de decisão disponível. Teorema: Se L é uma linguagem Turing-decidível então o seu complemento L também é Turingdecidível. Constrói-se a máquina de Turing desejada a partir de outra disponível, que decida L. Computabilidade e Decidibilidade Problemas que máquinas de Turing não representam também não se resolvem algoritmicamente (tese de Church). Isso motiva a investigar problemas computáveis, chegando a importantes conclusões a partir do conceito de decidibilidade para máquinas de Turing . Teorema: Toda Linguagem Turing-decidível é Turingaceitável. Monta-se uma máquina de Turing de aceitação, a partir da máquina disponível, de decisão. Teorema: Se L é uma Linguagem Turing-decidível então o seu complemento L também é Turingdecidível. Constrói-se a máquina de Turing a partir de outra, disponível, capaz de decidir L. Problema da Parada da Máquina de Turing Se houvesse uma máquina de Turing capaz de “descobrir” a saída de uma máquina de Turing M qualquer, então toda linguagem Turing-aceitável seria Turing-decidível. Pode-se resumir esta constatação na seguinte linguagem: K0={ρ(M)ρ(w) | M aceita w}.
Se K0 for Turing-decidível por alguma máquina M0, então toda linguagem Turing-aceitável será Turingdecidível. Se K0 é Turing-decidível, então K1={ρ(M) | M aceita ρ(M)} também o é, e a máquina de Turing M1 que a decide é composta de uma máquina de codificação, que codifica e copia a cadeia recebida w em ρ(w), e passa o controle para a máquina M0. Assim o resultado final de M0 será se e somente se: (i) w é ρ(M), e (ii) M aceita w, isto é, ρ(M). Mas isso é a definição de K1. Entretanto se K1 é Turing-decidível, então seu complemento também o é: K 1 ={w ∈ {I, c}*: w não é a codificação de uma máquina de Turing M, ou então w=ρ(M) para alguma máquina de Turing M que não aceita entrada ρ(M)}. Entretanto K 1 não é sequer Turing-aceitável, porque se o fosse haveria uma máquina de Turing M* que a aceita. Pela definição de K 1 , ρ(M*) ∈ K 1 se e somente se M* não aceita ρ(M*). Mas M* deve aceitar K 1 , assim ρ(M*) ∈ K 1 se e somente se M* aceita ρ(M*). Portanto M* aceita ρ(M*) se e somente se M* não aceita ρ(M*), o que é absurdo, logo deve ter havido erro na hipótese sobre M*, que não deve existir. Logo tem-se: Teorema: Nem toda linguagem Turing-aceitável é Turing-decidível. Teorema: Os complementos de algumas linguagens Turing-aceitáveis não são Turing-aceitáveis. Este é o famoso problema da parada da máquina de Turing (K0). Através dele, conclui-se que há problemas que não admitem solução algorítmica. Tais problemas são chamados insolúveis. Por outro lado, um problema é dito solucionável se existe um algoritmo que o resolve, isto é, se há um procedimento de decisão para ele. Teorema: Uma linguagem é Turing-decidível se e somente se tanto ela quanto o seu complemento são Turing-aceitáveis.
Teorema: Uma linguagem é Turing-aceitável se e somente se ela é a linguagem de saída de alguma máquina de Turing. Definição: Uma Linguagem é dita Turing-enumerável se e somente se existe uma máquina de Turing que enumera suas cadeias. Teorema: Uma linguagem é Turing-aceitável se e somente se ela é Turing-enumerável. Problemas Insolúveis sobre a Máquina de Turing Teorema: Os problemas a seguir são insolúveis: (i) Dada uma máquina de Turing M e uma cadeia de entrada w, M pára com a entrada w? (ii) Para uma específica máquina M, dada uma cadeia de entrada w, M pára com a entrada w? (iii) Dada uma máquina de Turing M, M pára com a fita de entrada vazia? (iv) Dada uma máquina de Turing M, há alguma cadeia de entrada com a qual M pára? (v) Dada uma máquina de Turing M, M pára com toda cadeia de entrada? (vi) Dadas duas máquinas de Turing M1 e M2, elas param com as mesmas cadeias de entrada? (vii) Dada uma máquina de Turing M, a linguagem que M aceita é regular? É livre de contexto? É Turing-decidível? Problemas Insolúveis envolvendo Gramáticas Teorema: Os problemas abaixo são insolúveis: (i) Para uma gramática arbitrária dada G e uma cadeia w, determinar se w ∈ L(G). (ii) Para uma específica gramática G0 e uma cadeia w, determinar se w ∈ L(G0). (iii) Dadas duas gramáticas arbitrárias G1 e G2, determinar se L(G1)=L(G2). (iv) Para uma gramática arbitrária G, determinar se L(G)=∅ Problemas Insolúveis sobre gram. livres de contexto Teorema: Os problemas a seguir são insolúveis: (i) Dadas 2 gramáticas livres de contexto G1 e G2, determinar se L(G1)∩L(G2)=∅. (ii) Para G, gramática livre de contexto, determinar se G é ambígua.
PCS-2427 - Lógica Computacional – Aula 23 – prof. João José Neto Assunto: Complexidade computacional Exemplo 2: Máquina de Turing com T(n)=2n2+13n+9
Conceito O conceito de complexidade está diretamente associado à computação em dispositivos físicos. Alguns problemas solucionáveis têm uma complexidade em tempo tão alta que sua utilização prática se torna inviável. Ex.: caixeiro viajante. Definição: Decidibilidade em tempo. Seja T: uma função numérica, L 0* uma linguagem, e M=(K, , , s) uma máquina de Turing com k fitas e com 0 . Diz-se que M decide L em tempo T se (s, #w#,#, ...,#)Mt (h, #Y#,#, ...,#) para algum t T(w) sempre que w L, e, sempre que w L, (s, #w#,#, ...,#)Mt (h, #N#,#, ...,#) para algum t T(w); Diz-se que L é decidível em tempo T se existir algum k > 0 e alguma máquina de Turing com k fitas que decide L em tempo T. A classe de todas as linguagens decidíveis em tempo T é denotada por TIME(T). Assim uma função do comprimento da entrada determina o limite para o número de passos da máquina de Turing. Assim não há função T tal que o T(n) < 2n + 4 para algum n 0 (já que, em qualquer computação, é necessário, no mínimo, percorrer a cadeia de entrada, apagá-la e escrever Y ou N).
>L
L
R#L
Corolário: Se L é decidida por uma máquina de Turing com k fitas em tempo T, então L é decidida em tempo T’=O(T2) por uma máquina de Turing clássica, com uma só fita.
R#L
R#
#
#
R#L
#
#
#
_
#L
# _
RNÃOR
#L
RSIMR
Teorema: Sendo f(n)=
a n j
j
um polinômio, e r>1, então f=O(rn).
b
Funções de complexidade T (n) O (1) : constante – mais rápido, impossível a a #L L #L T (n) O (log log n) : super-rápido b T (n) O (log n) : logarítmico – muito bom # # # T (n) O (n) : linear – é o melhor que se pode esperar se # algo não pode ser determinado sem examinar toda a entrada T (n) O (n log n) : limite de muitos problemas práticos, R R R R ex.: ordenar uma coleção de números T (n) O (n2) : quadrático T (n) O (nk) : polinomial – ok para n pequeno Determinar um limite superior para a função T pode não ser trivial. T (n) O (kn), O (n!), O (nn) : exponencial – evite! Entretanto, o objetivo da teoria da complexidade computacional é indicar, dentre as várias possíveis máquinas de Turing que decidem Simulações limitadas no tempo uma dada linguagem, aquela capaz de terminar em T passos, sendo T Teorema: Se uma linguagem L é decidida em tempo T1 por uma o menor possível, ou então, se isso não puder ser feito, apresentar máquina de Turing M1 com fita duplamente infinita, então L é uma demonstração rigorosa da inviabilidade de uma máquina tão decidida em tempo T2 por uma máquina de Turing clássica M2, com rápida. uma fita. Neste caso, T2(n)=6T1(n)+3n+8 para todo n. Taxa de crescimento de funções Teorema: Se uma linguagem L é decidida em tempo T1 por uma O mais significativo no estudo da complexidade computacional é a máquina de Turing M1 com k fitas, então L é decidida em tempo T2 taxa de crescimento da função T. São irrelevantes para tal estudo os por uma máquina de Turing clássica M2, com uma fita. Neste caso, T2(n)= 4T1(n)2+(4n+4k+3)T1(n)+5n+15. termos de ordem inferior e os valores exatos das constantes. _
#
NÃO
Outra leitura desses resultados é que, em tempo polinomial, todas as variantes da Máquina de Turing podem ser simuladas usando-se o modelo clássico, com uma única fita semi-infinita.
Complexidade no espaço É possível transpor os métodos aqui esboçados para a avaliação da resposta temporal das máquinas de Turing para um estudo similar, visando à medida da quantidade de espaço que esses dispositivos Definição: Sejam f e g funções de para . Escreve-se f=O(g) se e utilizam quando decidem a linguagem que representam. somente se há uma constante c > 0 e um inteiro n0 tal que: f(n) Para isso o alvo é a obtenção da relação que existe entre o tamanho da cadeia de entrada e a quantidade de fita (número de células da fita) c.g(n), para todo n n0. ocupada pela máquina ao decidir tal cadeia. R#L
j 0
SIM
Isso tudo significa que, dentro de certos limites, o tempo de resposta da máquina que decide uma linguagem pode ter seu grau modificado apenas escolhendo-se convenientemente o tipo de máquina de Turing utilizada em sua implementação.
d
Exemplo 1: Máquina de Turing com T(n)=2n+4
>
Teorema: Se L é decidida em tempo T por alguma máquina de Turing bidimensional, então L é decidida em tempo T’=O(T3) por uma máquina de Turing de 4 fitas.
É preciso notar que existe uma interdependência entre a complexidade espacial e temporal, que tal dependência reflete o método utilizado pela máquina no processamento das suas cadeias de entrada, e que nem sempre as funções que representam tais complexidades de tempo e de espaço são “complementares”. Assim, por exemplo, modificações em uma Máquina de Turing que aumentem o seu tempo de processamento nem sempre garantem a obtenção de outra máquina de Turing cujas necessidades de memória de trabalho sejam inferiores. Complexidade de Algoritmos Como, de acordo com a Tese de Church, Máquinas de Turing são representações formais de algoritmos, o estudo da complexidade das Máquinas de Turing proporciona os fundamentos para a compreensão da importante prática do estudo da complexidade de algoritmos. Transpor para os algoritmos as métricas utilizadas no estudo da complexidade das Máquinas de Turing é muito simples e intuitivo, e se resume à estimativa do tempo de resposta do algoritmo através da contabilização dos tempos de execução das instruções que o compõem, em função das entradas que lhe são fornecidas, bem como da quantidade de memória exigida para a representação e manipulação dos seus dados, especialmente aqueles implementados utilizando alocação dinâmica de memória. Este importantíssimo assunto não é coberto aqui porque foge ao escopo desta disciplina.
PCS-2427 - Lógica Computacional – Aula 24 – prof. João José Neto Assunto: Classes de complexidade computacional se (s, #x#,#, ..., #) Mt (h, #f(x)#,#, ..., #), para qualquer 1. Classe * Definição: Define-se (classe das linguagens decidíveis cadeia x ∈ Σ e para algum t≤T( x ). por máquina de Turing determinística, em tempo Definição: Diz-se que f é computável em tempo polinomial) como: = { TIME (nd) | d>0}. polinomial se existir algum T que seja um polinômio. Os problemas da classe são aqueles que permitem Definição: Sejam as linguagens L1 ⊆ Σ1* e L2 ⊆ Σ2*. soluções computacionais realísticas (suas exigências de Uma função τ: Σ1* → Σ2* computável em tempo tempo de processamento e de espaço são razoáveis). polinomial é chamada transformação de L1 para L2 Um problema L em exige uma máquina de Turing em tempo polinomial se e somente se, para cada cadeia determinística que o decida em tempo polinomial. x∈Σ1*, x∈L1 ⇔ τ(x)∈L2 2. Classe Definição: Uma linguagem L é dita -completa se e Seja T: Ν → Ν uma função numérica, L ⊆ Σ* uma somente se L∈ , e se existir uma transformação linguagem, e M = (K, Σ, ∆, s) uma máquina de Turing polinomial de L’ para L para toda linguagem L’∈ . não determinística Teorema: Seja L uma linguagem -completa. Nessa situação, = ⇔ L∈ . (É pena que isso não Definição: Diz-se que M aceita L em tempo não determinístico T se para todo w ∈ Σ*, w∈L se e signifique que = , mas apenas que teria L∈ como somente se (s, #w#) Mt (h, vσu) para algum v, u ∈ Σ*, condição necessária e suficiente. Está em aberto, até onde se sabe, se isso é verdade ou não). σ ∈ Σ, e t ≤ T( w ). -Completos: Definição: NTIME(T) = classe das linguagens L 4. Exemplos de Problemas aceitáveis em tempo não determinístico T (se houver Há mais de 3000 problemas -completos catalogados uma máquina de Turing não-determinística que aceita L (ver livro de Garey e Johnson). Suas definições são em tempo não-determinístico T). todas equivalentes entre si (ver livro do Sipser). Seu Definição: = classe das linguagens decidíveis não- tratamento prático costuma ser feito através de métodos determinísticamente em tempo polinomial – é de aproximação. Três deles são: definida como = {NTIME (nd) | d > 0}. (i) Programação Linear Inteira – determinação da Definição: Uma computação é considerada infinita se solução de um sistema de equações lineares, cujos necessitar de mais de T( w ) passos para a entrada w. coeficientes e soluções são números inteiros (ver Aplica-se na prática esta definição para a detecção de detalhes no livro do Lewis e Papadimitriou); loops em algoritmos com resposta temporal conhecida. (ii) Ciclo Hamiltoniano – dado um grafo, determinação d Teorema: ⊆ {TIME( r n ): r, d > 0}. da existência ou não de um ciclo que percorra todos os seus vértices, passando uma só vez em cada um; 3. Classe -Completo Definição: Sejam Σ e ∆ alfabetos e f: Σ*→∆* uma (iii) Caixeiro Viajante – determinação do ciclo hamiltoniano de comprimento mínimo para o grafo função de cadeia para cadeia. Essa função f é dita ponderado das conexões existentes entre as cidades computável em tempo T por uma máquina de Turing de um conjunto dado. determinística com k fitas M=(K, Σ’, δ, s) se e somente Discute-se aqui só o problema (ii) acima mencionado.
∪
∪
∪
Existência de Ciclo Hamiltoniano – Na determinação da existência de um ciclo hamiltoniano em um grafo, a cadeia de entrada para a máquina de Turing (determinística) decisora corresponde à descrição do grafo, no qual se deseja determinar a existência ou não de um ciclo hamiltoniano. Um possível algoritmo para resolver este problema de decisão determina todas as permutações dos n vértices do grafo, e verifica se cada uma delas é ou não um Ciclo Hamiltoniano. Sua complexidade temporal é O(n!), resposta de natureza fatorial. Não se conhece (ainda) solução polinomial para este problema. Para resolver polinomialmente problemas em necessita-se de uma máquina de Turing determinística capaz de verificar em tempo polinomial se uma cadeia de entrada qualquer pertence ou não à linguagem que representa o problema. Verificação de Ciclo Hamiltoniano – No problema de verificação de um ciclo hamiltoniano, a cadeia de entrada de uma máquina de Turing (determinística) verificadora corresponde à descrição do grafo, e a cadeia a ser verificada representa uma proposta de ciclo hamiltoniano, a ser testada. Isso também constitui um problema de decisão. É simples verificar se uma cadeia proposta representa ou não um ciclo Hamiltoniano: dada uma seqüência de n vértices, verifica-se primeiramente se ela é de fato uma permutação dos vértices do grafo, e em seguida, se cada par de vértices consecutivos constitui realmente uma aresta do mesmo. A complexidade deste algoritmo é O(nk), logo trata-se de outro caso de problema verificável em tempo polinomial. Definição: Um clique em um grafo não-orientado G=(V,E) é um subconjunto C⊆V do conjunto V de vértices tal que para cada par de vértices em C exite
uma aresta que os interliga. Em outras palavras, o subgrafo determinado por C é completo. Em alguns casos, o termo clique refere-se ao próprio subgrafo. Definição: Clique ou Subgrafo completo de um grafo G=(V,E) é um subconjunto C ⊆ V tal que para cada par de vértices em C exite em E uma aresta que os interliga. Definição: k-clique é um clique com k vértices. Definição: O problema clique consiste em encontrar um clique máximo, (ou, conforme o autor, determinar todos os cliques, ou um k-clique) em um grafo G não orientado. Trata-se de um problema da classe . Um verificador V (polinomial) para o problema clique, com c sendo o clique a ser verificado: Para a entrada G, k , c as 2 condições abaixo devem ser satisfeitas: (i) c deve ser um conjunto de k vértices do grafo (ii) o grafo deve contém todas as arestas que conectam os vértices em c. Apesar de ser bem complicado determinar a existência de um ciclo hamiltoniano num grafo G, dado o grafo e um ciclo, verificar se tal ciclo é um ciclo hamiltoniano de G pode ser feito em tempo polinomial. Apesar da complexidade do problema geral do clique, em certos casos favoráveis, como o dos grafos planares, a solução pode ser obtida em tempo polinomial. 5. Outros problemas (i) CLIQUE = { | G é um grafo não orientado, com k-clique}; (ii) SUBSET-SUM = { | S={x1, x2, ..., xk} e para algum {y1, y2, ..., ym} ⊆ {x1, x2, ..., xk} tem-se Σ yi = t}. Ex: <{4, 11, 16, 21, 27}, 25> ∈ SUBSET-SUM pois 4 + 11 = 25. SUBSET-SUM está em . 6. Classe × Classe Todos os problemas de complexidade P são também de complexidade . O inverso “parece” não ser verdade. Porém não se pode afirmar isso. Alguns problemas “parecem” não ter soluções passíveis de serem obtidas
em tempo polinomial. Entretanto, os algoritmos podem simplesmente não ser conhecidos, ainda! 7. Redução de Problemas Redução é uma forma de converter um problema A em outro, B, de modo que a solução do problema B pode ser usada para resolver o problema A.
A classe -completo então relaciona todos os problemas de , através da redução. Se uma solução polinomial for encontrada para um problema de completo, então todos os outros problemas de também poderão ser solucionados por um algoritmo polinomial, isto é, = (provar-se-á que = ).
Notação: A ≤ B lê-se: A é redutível a B. Ex.1: o problema de ir de São Paulo a Paris se reduz ao de comprar uma passagem aérea de SP a Paris, que se reduz ao problema de conseguir dinheiro para isso,... Ex.2: o problema de medir a área de um retângulo se reduz ao problema de medir sua altura e largura (dado que efetuar uma multiplicação é tarefa elementar). A redução consiste em definir uma função f que reduz A em B, de forma que, se w é entrada de A, a solução de w por A é equivalente à solução de f(w) por B. Se A e B são problemas de decisão, então a solução de w por A é a mesma solução de f(w) por B.
Para definir a classe -completo, deve-se provar que um problema está, de fato, em e que outros de podem ser reduzidos a ele em tempo polinomial (isto seria o “começo” da classe -completo). Teorema: Se B∈
-completo e B∈ , então
=
.
Prova: 1. Se A ≤P B e B∈ , então A∈ (teorema de slide anterior). 2. Como B∈NP-completo, todo A∈ , A≤PB (def. de NP-completo). 3. Se B∈ e com 2 (todo A≤PB), então todo A∈ e também a ( = )! Teorema: Se B∈ C∈ -completo.
-completo e B ≤P C e C∈
, então
Prova: Dado que B∈ -completo e B≤PC e C∈ , para Mostra-se que AMT é redutível a HALTMT: AMT ≤ provar que C∈ -completo, basta mostrar que todo HALTMT. Como AMT é indecidível, HALTMT também é. A∈ , A≤PC. 1. Como B∈ -completo, então A≤PB. Teorema: Se A≤ ≤B e A é indecidível, então B também é. 2. Como B ≤ C, então A≤ B ≤ C. Portanto, A≤ C P P P P Teorema: Se A≤ ≤B e B é decidível, então A é decidível. 9. Outras Classes de Complexidade Prova: Seja MA a MT que decide A e MB a MT que PSPACE – problemas que podem ser decididos em decide B: MA = “Para a entrada w: (i) Calcule f(w). (ii) espaço polinomial em uma MT determinística Execute MB em f(w). (iii) Se MB aceitar, aceite. Se não, analogia, para a complexidade espacial, com a classe rejeite.” Assim, se B é decidível, A também é decidível. EXPTIME – problemas que podem ser resolvidos em Teorema: Se A ≤ B e B∈ , então A∈ . tempo exponencial. 8. Problemas NP-completos Conjectura sobre inclusão das classes: Um problema B é NP-completo se: (i) B ∈ e (ii) < < SPACE < EXPTIME ∀A∈ pode ser reduzido a B em tempo polinomial 10. Bibliografia específica desta aula (A ≤P B) . Sipser, M. Introduction to the Theory of Computation. -completo e B∈P, então = . Teorema: Se B∈ PWS Publishing Company, Boston, MA. 1997. Teorema: Se B∈ -completo e B ≤P C e C∈ , Garey, Michael R.; Johnson, David S. Computers and então C∈ -completo. Intractability: A Guide to the Theory of NP-Completeness W. H. Freeman, 1979. ISBN 0-7167-1045-5 .
PCS-2427 – Lógica Computacional – Aula 25 – Prof. João José Neto Assunto: Exercícios de fixação dos conceitos Linguagens livres de contexto 1. Projetar uma gramática livre de contexto para a linguagem definida por uma expressão regular 2. Desenhar a árvore de sintaxe de uma sentença dada, com base em uma gramática fornecida. 3. Projetar uma gramática livre de contexto para uma linguagem cujas propriedades são fornecidas através de uma descrição em linguagem natural. 4. Usando como base uma gramática fornecida, explicitar uma derivação mais à esquerda e uma derivação mais à direita para uma sentença fornecida. 5. Definir, através de uma gramática livre de contexto, a sintaxe das notações meta-lingüísticas utilizadas para a descrição de outras linguagens. Linguagens e Gramáticas Sensíveis ao Contexto: 6. Construir gramáticas irrestritas para linguagens propriedades de suas sentenças.
definidas
pelas
Linguagens Recursivas e Recursivamente Enumeráveis. Gramáticas Irrestritas 7. Construir uma máquina de Turing capaz de decidir uma linguagem especificada através da discrição das propriedades de suas sentenças. 8. Construir uma máquina de Turing capaz de semi-decidir uma linguagem regular dada. 9. Provar para as linguagens recursivas e recursivamente enumeráveis a propriedade de fechamento em relação às operações de concatenação, união e fecho de Kleene. 10. Dada uma gramática irrestrita através de suas produções, determinar qual é a linguagem gerada pela gramática e derivar, passo a passo, uma sentença de comprimento maior ou igual a 7. Desenhar o grafo de derivação desta sentença.
Forma normalizada das gramáticas Construir gramáticas para as linguagens especificadas através propriedades de suas sentenças, e normalizá-las.
de
Equivalências entre dispositivos gramaticais e autômatos 12. Exemplificar, usando algumas linguagens regulares à escolha, cada uma das possibilidades de representação acima enumeradas: a construção do conjunto usando os três operadores básicos, os dois tipos de autômatos finitos, as expressões regulares e os dois tipos de gramáticas lineares. 13. Estabelecer alguns mapeamentos entre as representações possíveis das linguagens regulares: (a) entre expressões regulares e autômatos finitos;
(b) entre autômatos finitos e gramáticas lineares; (c) entre gramáticas lineares e autômatos finitos. 14. Escolher uma linguagem livre de contexto não muito complexa e representá-la nas diversas formas acima mencionadas. Identificar, em cada tipo de representação, a maneira como são representadas as concatenações, as uniões, as estrelas de Kleene, os aninhamentos sintáticos. 15. Estabelecer ao menos uma forma sistemática de mapeamento de uma gramática livre de contexto para um autômato de pilha. Aplicar para uma linguagem livre de contexto a sua escolha. 16. Escolha uma linguagem dependente de contexto que não seja livre de contexto. Represente-a usando notação de conjuntos, usando uma gramática dependente de contexto qualquer, e depois outra na forma normalizada. Represente-a também usando uma máquina de Turing. 17. Repita o exercício anterior para uma linguagem irrestrita à sua escolha que não seja dependente de contexto. Computabilidade gramatical 18. Projete uma máquina de Turing que represente a linguagem { w∈{Ι} ∈{Ι}∗ | |w|= ∈ }. Use em seguida o método apresentado na | |=n |= 2, n∈ demonstração do teorema 1 para converter essa máquina de Turing em uma gramática que compute a função ƒ(n)=n2. Exercite a máquina de Turing e a gramática para o caso de n=4. (Lembrar que quadrados perfeitos podem ser obtidos como a soma de um número finito de termos da série de números naturais ímpares, iniciada em 1). 19. Construa diretamente uma gramática que compute a mesma função do exercício anterior, sem construir antes a máquina de Turing. Exercite-a para n=4. 20. Repita o exercício 2 para outras funções naturais algébricas de uma variável, tais como: 5n, 3n2, 2n, n2+3n+2, nn, n!, etc. Taxa de crescimento de funções 21. No estudo da complexidade computacional dos algoritmos, é freqüente que se chegue a expressões contendo combinações de funções como as listadas a seguir. Determine a taxa de crescimento dessas funções, e coloque-as em ordem crescente de sua taxa de crescimento, indicando, se houver, quais delas apresentam taxas iguais de crescimento: n^2; 2^n; n*lg(n); n!; 4^n; n^n; n^(lg(n)); 2^(2^n); 2^(2*n); 2^(2^(n+1)); (2^(100))*n; 2^(1000) (usou-se o operador ^ para indicar potenciação, e * para indicar produto, e lg para indicar logaritmo em base dois)
PCS-2427 - Lógica Computacional – Aula 26 – prof. João José Neto
Assunto: Lista de exercícios sobre Computabilidade, Algoritmos e Complexidade Computacional 1. Construa um esquema de máquina de Turing que promova a concatenação de duas cadeias v e w sobre o alfabeto {x, y}, convertendo o conteúdo da sua fita de trabalho de #v#w# para #vw# 2. Usando blocos de construção elementares, construa um esquema de máquina de Turing converta o conteúdo de sua fita de #w# onde w é qualquer cadeia de x’s e y’s, na configuração #w#v#, onde v é o reverso da cadeia w. 3. Desenhe uma máquina de Turing M que reconheça as linguagens: a) L(M) = {xny2nzn | n 0}. b) L(M) = {xmynxmyn | m, n 4. Determine a linguagem que a MT ao lado reconhece. O que ocorre ao serem processadas as cadeias: xyxxy, xxx e yyy?
0} #
y
x y #
5. Mostre que a linguagem L = {wi | w2i não é aceito por MT} não é aceita por nenhuma máquina de Turing. (observar que L tem uma definição semelhante à definição da linguagem diagonalização, construída a partir de codificações das MT) 6. Mostre que o problema da parada, o conjunto de pares ordenados (M,w) tais que M pára (com ou sem aceitação) ao receber a entrada w é recursivamente enumerável, mas não recursivo. 7. Demonstre que as linguagens recursivas e as linguagens recursivamente enumeráveis são fechadas sob as operações de união, interseção, concatenação e fecho de Kleene. 8. Demonstra-se (Teorema de Rice) que nenhum dos dois problemas abaixo é decidível. Determinar se eles são ou não recursivamente enumeráveis: a) L(M) contém pelo menos duas sentenças? b) L(M) é infinita? 9. Mostrar que os problemas a seguir são decidíveis: a) o conjunto de códigos para máquinas de Turing que nunca fazem um movimento à esquerda
b) o conjunto de pares (M, w) tais que a máquina de Turing M, iniciada com a entrada w, nunca visita qualquer célula da fita mais de uma vez. 10. Mostre que o problema descrito pela linguagem seguinte é recursivamente enumerável: O conjunto de triplas (M1, M2, M3) tais que L(M1) = L(M2)L(M3); isto é, a linguagem da primeira é a concatenação das linguagens das outras duas máquinas de Turing. 11. Para cada problema abaixo, mostre se é recursivo, se é recursivamente enumerável mas não recursivo, ou se não é sequer recursivamente enumerável: a) O conjunto de todos os códigos correspondentes a máquinas de Turing que param em resposta a pelo menos uma particular entrada. b) O conjunto de todos os códigos correspondentes a máquinas de Turing que entram em loop em resposta a pelo menos uma particular entrada. 12. Pesquise em livros e sites web sobre teoria da computação um pouco mais sobre classes de complexidade de problemas computacionais. Com base nessas informações, identifique alguns problemas NPcompletos em sua área de atuação. 13. Sem dúvida o mais famoso dos problemas NPcompletos é o problema do caixeiro viajante. Pesquise, nas fontes de que você dispõe, uma formulação precisa deste problema e estude uma demonstração de que ele é NP-completo. Imite a formulação e a demonstração para outras variantes deste problema. 14. As linguagens recursivamente enumeráveis não são fechadas em relação à operação de complementação. Provar que elas são fechadas em relação às operações de união e de interesecção. 15. Pesquise, em boas fontes, informações técnicas sobre como determinar analiticamente a complexidade de algoritmos. Selecione um conjunto representativo de algoritmos clássicos de seu maior interesse e estude-os do ponto de vista de sua complexidade no tempo e no espaço. Relacione os resultados dessa pesquisa com os conhecimentos estudados nesta disciplina, com base na máquina de Turing. Existem excelentes
catálogos e manuais de análise da complexidade de algoritmos. 16. Escolha e estude rigorosamente um problema bem conhecido e não muito complexo (por exemplo, busca ou de ordenação de dados), e selecione dois algoritmos básicos que os resolvam, analisando-os comparativamente, de acordo com diversos critérios, objetivos e pontos de vista: a) modelando-o com máquina de Turing e avaliando o a resposta no tempo da computação efetuada por esta máquina em função do número de dados tratados; b) efetuando análise similar, relativa à quantidade de espaço em fita necessário para a decisão da cadeia de entrada; c) implementando o mesmo método de resolução em alguma linguagem de baixo nível ou de máquina, para a qual se disponha do tempo de execução que cada instrução consome, e avaliando quantitativamente o tempo de resposta deste programa em função do número de dados tratados; d) efetuando análise similar, relativa à quantidade de espaço em memória/disco necessário para que os dados de entrada sejam totalmente processados; e) implementando o mesmo método de resolução em alguma linguagem de alto nível, para cujas instruções se conheça o código-objeto gerado pelo compilador, e portanto o tempo necessário para a execução de cada instrução, e avaliando quantitativamente o tempo de resposta deste programa em função do número de dados tratados; f) efetuando para esse programa uma análise similar, referente às exigências de espaço em memória e/ou disco. g) avalie a sensibilidade dessa análise em relação a variações na representação física dos dados e sua organização lógica (por exemplo, representação como vetor de vetores, como matriz bidimensional ou como lista ligada, dados ordenados ou não, possibilidade de indexação direta ou acessos através de ponteiros ou similares, etc).
PCS-2427 – Lógica Computacional – Aula 27 – Prof. João José Neto Assunto: Exercícios para Revisão 1. Exprimir a linguagem L={x∈ ∈{0,1}* | x representa inteiros binários positivos}: (a) por meio de uma expressão regular; (b) por meio de uma gramática linear à esquerda; (c) por meio de uma gramática linear à esquerda; (d) por meio de um autômato finito não-determinístico; (e) por meio de um autômato finito determinístico mínimo; (f) por meio de uma máquina de Turing. 2. Dada a gramática livre de contexto G=(V,Σ Σ,P,S) onde P = { S→ →aSa , R S→ →bSb , S→ →ε }, provar que esta gramática gera a linguagem (G)={xx | x∈ ∈{a,b}*}. Montar um autômato de pilha que represente esta linguagem (G). Montar um autômato de pilha estruturado que represente (G). Finalmente, montar uma máquina de Turing que decida esta mesma linguagem (G). Mostre que é impossível representar essa linguagem com um autômato finito. 3. Prove que, no exercício anterior, substituindo o terminal b por a, (G) passa a representar uma linguagem regular. Apresente um autômato finito determinístico mínimo que represente tal linguagem. 4. Para a gramática G=(V,Σ Σ,P,S) onde P = { S→ →ABC , AB→ →0AD , AB→ →1AE, DC→ →B0C , EC →B1C , D0→ →0D , D1→ →1D , E0→ →0E , E1→ →1E , AB→ →ε , C→ →ε , 0B→ →B0 , 1B→ →B1 }, mostrar que (G)={xx|x∈ ∈{0,1}*}. Construir uma máquina de Turing que aceite todas as sentenças geradas por essa gramática e nada mais. Fazendo uma análise cuidadosa, mostrar por que a solução apresentada está correta. 5. Montar uma gramática G que gere a linguagem (G)={ 0i1j0i1j | i, j > 0}, e mostrar que essa gramática gera todas as sentenças da linguagem em questão e nada mais. Construir uma máquina de Turing que aceite todas as sentenças geradas por essa gramática e nada mais. Mostrar por que a solução proposta está correta. 6. Mostre que a gramática G=(V,Σ Σ,P,S), onde P = { S→ →a , S→ →SbS } é ambígua. Apresente uma outra gramática livre de contexto nãoambígua que represente a mesma linguagem (G). Construa autômatos de pilha que imitem o comportamento de cada uma das duas gramáticas. 7. A linguagem L={ aibjck | i=j ou j=k, onde i, j, k > 0}, livre de contexto, é inerentemente ambígua, no sentido de que para ela é impossível repetir o que foi feito no exercício anterior.
8. Diz-se de uma gramática livre de contexto que ela está em Forma Canônica de Pares (canonical two form) quando os lados direitos de suas regras forem de quatro tipos apenas: (a) uma seqüência de dois não-terminais; (b) um não-terminal isolado; (c) um terminal isolado; (d) a cadeia vazia. Adicionalmente, se S→ →ε for uma das regras, sendo S a raiz da gramática, então nas regras dos tipos (a) e (b) o não terminal S não pode ser usado. Nessas condições, pede-se converter para esta forma canônica de pares a gramática cujas produções estão contidas no conjunto P= { S→ →aAC , A→ →aB , A→ →bAB , B→ →b , C→ →c }. 9. Outra forma normal para gramáticas livres de contexto é a Forma Normal de Chomsky. Diz-se que uma gramática livre de contexto está na Forma Normal de Chomsky quando o lado direito de cada uma de suas regras é de uma das formas seguintes: (a) uma seqüência de dois não-terminais; (b) um terminal; (c) a cadeia vazia. Como no caso anterior, impõe-se que, caso a raiz seja definida como uma cadeia vazia, então o não-terminal correspondente à raiz não pode ser utilizado em regras do tipo (a). Pede-se converter para a Forma Normal de Chomsky a gramática do exercício anterior, dada pelas regras P={ S→ →aAC , A→ →aB , A→ →bAB , B→ →b , C→ →c }. 10. Uma terceira forma normal para gramáticas livres de contexto, denominada Forma Binária Padrão, restringe o tipo de regra a uma única forma: uma seqüência de dois símbolos do vocabulário (ou seja, cada um é, indiferentemente, ou um terminal ou um não-terminal). Converter para esta forma binária padrão a mesma gramática dos exercícios anteriores, dada pelas regras P= { S→ →aAC , A→ →aB , A→ →bAB, B→ →b , C→ →c }. 11. Outra forma normal famosa é a Forma Normal de Greibach, na qual os lados direitos de todas as regras de produção devem ser colocados em uma das formas seguintes: (a) S→ →ε onde S é a raiz da gramática; (b) um terminal; (c) um terminal, seguido de uma seqüência de nãoterminais, que não envolva a raiz S. Pede-se colocar na Forma Normal de Greibach a gramática cujo conjunto de produções é o seguinte: P={ S→ →TbT , T→ →TaT , T→ →ca }.