Problema

Propaganda
Conceitos Básicos
Vocabulário
Cadeias
Linguagens
Expressões Regulares
Problema X Linguagem
Alfabeto ou Vocabulário: Conjunto finito não
vazio de símbolos. Símbolo é um elemento
qualquer de um alfabeto.
Ex: {A,B,C,….Z} alfabeto latino (maiúsculas)
{, , , , , …, } alfabeto grego
{0,1} alfabeto binário
{0,1,2,3,4,5,6,7,8,9} alfabeto de dígitos
{a, b}
Cadeia ou palavra: Concatenação de símbolos de
um alfabeto. Define-se como cadeia vazia ou nula
uma cadeia que não contém nenhum símbolo.
Ex: aab
123094
l - cadeia nula
Comprimento de cadeia: Número de símbolos de
uma cadeia.
Ex: |aab| = 3
|123094|=6
|l | =0
Concatenação
de
cadeias:
Define-se
a
concatenação z de uma cadeia x com uma cadeia y
como sendo a justaposição dos símbolos de ambas
as cadeias, formando a cadeia xy.
|z| = |x| + |y|
Ex:
x = abaa; y = ba  z = abaaba |z|=4+2=6
x = ba; y = l  z = ba |z|=2+0=2
Produto de alfabetos: É o produto cartesiano de
alfabetos.
Ex:
V1 = {a,b}; V2 = {1, 2, 3}  V1.V2 = V1xV2 =
{a1, a2, a3, b1, b2, b3}
Observe que V1.V2  V2.V1
Exponenciação de alfabetos: São todas as
cadeias de comprimento n sobre V (Vn). V0={l},
V1=V, Vn=Vn-1.V
Ex:
V = {0, 1}
V3 = V2.V = (V.V).V = {00, 01, 10, 11}.{0,1} = {000,
001, 010, 011, 100, 101, 110, 111} |V|=8
|Vn| = mn onde |V| = m
Fechamento (Clausura) de um Alfabeto:
Seja A um alfabeto, então o fechamento de A é
definido como
A* = A0  A1  A2  ...  An  ...
Portanto A* = conjunto das cadeias de qualquer
comprimento sobre o alfabeto A.
Ex:
A = {1}
A* = {l, 1, 11, 111, ...}
Fechamento Positivo de A: A+ = A* - {l} (todas as
cadeias não vazias sobre o alfabeto A)
Exemplo:
Se T = {a, b} e NT = {A, B, C}
Então (T U NT) * =
{a, b, A, B, C}* = {l} U {a, b, A, B, C} U {a, b, A, B, C}2 U
{a, b, A, B, C} 3 U …. =
{l, a, b, A, B, C, aa, ab, ba, bb, aA, aB, aC, bA, bB, bC,
Aa, Ab, Ba, Bb, Ca, Cb, AA, AB, AC, BA, BB, BC, CA, CB,
CC, aaa, aab, aba, abb, baa, bab, bba, bbb, aaA, aaB, aaC,
…, Aaa, …, ABC, …, CCC, …
Ou seja, (T U NT) * consiste de todas as cadeias, de
qualquer comprimento, de símbolos de T e/ou NT.
Linguagem é um conjunto de cadeias de símbolos
sobre um alfabeto/vocabulário, V. É um
subconjunto específico de V*. Estas cadeias são
denominadas sentenças da linguagem, e são
formadas pela justaposição de elementos
individuais, os símbolos da linguagem.
Ex:
e bc)
V = {a, b, c}
L = {ab, bc} ( linguagem formada pelas cadeias ab
 L  V2
Formadores de Conjuntos
Expressões que ajudam a descrever uma linguagem (em geral
infinita):
L = { w | algo sobre w }
O conjunto de cadeias w tais que …(o que for dito sobre w à
direita)
Exs.:
1. L={ w | w consiste de um número igual de 0’s e 1’s }
2. L={ w | w é um número inteiro binário primo }
3. L={ w | w é um programa em C sintaticamente correto }
4. L={ 0n 1n | n 1} = {01, 0011, 000111, ...}
5. L={0i 1j | 0 i  j} = {l, 01, 1, 11, 111..1, 011, 0011, 00111, ...}
6. L={abn  anb| n>=0} (linguagem formada por todas as cadeias
que começam com "a" seguido de um número qualquer de "b"'s
OU começam com um número qualquer de "a"'s seguidos de um
"b", por exemplo a, b, ab, abb, aab, aaab, ...). Também se
escreve abn + anb
Expressões Regulares (ER)
Uma ER sobre um alfabeto  é definida como:
a)  é uma ER e denota a linguagem vazia
b) l é uma ER e denota a linguagem contendo
a palavra vazia, ie {l}
c) Qualquer símbolo x   é uma ER e
denota a linguagem {x}
d) Se r e s são ER denotando as linguagens R
e S então:
•
•
•
(r+s) ou (r|s) é ER e denota a linguagem R  S
(rs) é ER e denota a linguagem RxS = {w=uv | u
 R e v S}
(r*) é ER e denota a linguagem R*
9
Exemplos
• 00 é uma ER denotando a linguagem {00}
• (0+1)* denota a linguagem formada por todas
as cadeias de 0´s e 1´s
• (0+1)* 00 (0+1)* denota todas as cadeias de
0´s e 1´s com ao menos dois 0´s consecutivos
• a+b*c denota um único a ou zero ou mais vezes
b seguido de c
10
• (0+1)* 001 denota todas as cadeias de 0´s e
1´s terminadas em 001
001, 000001, 101001, 111001, ...
• 0*1*2* denota qualquer número de 0´s seguido
por qualquer número de 1´s seguido por
qualquer número de 2´s
l, 0, 1, 2, 12, 001, 1112, 001122,...
• 01* + 10* denota a linguagem consistindo de
todas as cadeias que são um único 0 seguido
por qualquer número de 1´s OU um único 1
seguido por qualquer número de 0´s.
0, 01, 01111, 1, 10, 100000, ...
11
Omissão de parênteses
• Para omitir parênteses devemos respeitar:
– O fecho (*) tem prioridade sobre a concatenação (rs), que
tem prioridade sobre a união (r+s).
– A concatenação e a união são associadas da esquerda para
a direita.
– Ex: 01* + 1 é agrupado como (0(1*)) + 1 => L = {1, 0, 01,
011,...}
• Usamos parênteses quando queremos alterar a prioridade:
• (01)* + 1 => L = {1 U (01)n | n >= 0} = {1, l , 01, 0101,...}
• 0(1* + 1) => L = {w  {0,1}* | w começa com 0 seguido de 1n |
n>=0}  Lei distributiva à esq = 01* + 01 = {0,01,011,0111,...}
12
Escreva a ER equivalente a:
• O conjunto de cadeias sobre {0,1} que
termine com três 1´s consecutivos.
(0+1)*111
• O conjunto de cadeias sobre {0,1} que
tenha ao menos um 1.
(0+1)*1(0+1)*
• O conjunto de cadeias sobre {0,1} que
tenha no máximo um 1.
0*(1+l)0*
13
LINGUAGEM OU PROBLEMA??
• A Tese de Church-Turing diz que o
conjunto de problemas que podem ser
resolvidos por Máquinas de Turing
(MT) coincide com o conjunto de
problemas que podem ser resolvidos
pelos computadores.
• Acontece que, como veremos mais
tarde, o que as MT fazem é
reconhecer Linguagens.
• Como, então, relacionamos Linguagens
14
e Problemas?
LINGUAGEM OU PROBLEMA??
Quando escolhemos a Máquina de Turing como modelo de
computabilidade, definimos então um Problema como
equivalente a decidir se uma dada cadeia pertence à uma
linguagem específica: o conjunto de cadeias que são
soluções do problema. Assim, um problema é sinônimo de
decidir a pertinência de uma cadeia a um conjunto (uma
linguagem). Mais precisamente:
Se  é um alfabeto e L é uma linguagem sobre , então o
problema L é:
Dada uma cadeia w em *, decidir se w está ou não em L.
(Questão de Decisão)
LINGUAGEM OU PROBLEMA??
Ex.: O problema de testar se um número binário é um
número primo pode ser expresso pela linguagem Lp que
consiste em todas as cadeias binárias cujo valor como
número binário é primo.
Ou seja, dada uma cadeia de 0’s e 1’s, diremos sim se a
cadeia for a representação binária de um primo, ou
diremos não, caso contrário. O conjunto das cadeias
que satisfazem a condição de número binário primo
representa a linguagem-solução do problema.
Assim, se queremos estudar a eficiência da solução
desse problema, basta estudarmos a eficiência de se
verificar se uma dada cadeia candidata pertence ou
não à Linguagem Lp.
Linguagem ou Problema?
• São a mesma coisa. O termo usado depende do ponto de
vista.
• Encarar problemas como uma questão de pertinência de
conjunto (pertence ou não à linguagem) tem sido útil aos
estudos da teoria da complexidade.
• Nessa teoria, estamos interessados em provar limites
inferiores sobre a complexidade de certos problemas
(p.ex. provar que eles não podem ser resolvidos em um
período de tempo menor que o exponencial no tamanho de
sua entrada).
• Acontece que a versão baseada em linguagens (de decisão
sobre pertinência) de problemas conhecidos são tão difíceis
quanto suas versões do tipo “resolva isso”.
• Ao reduzirmos um problema para sua versão de pertinência
e provarmos que é difícil resolvê-la, então podemos
concluir que resolver o problema inicial será igualmente
difícil. (Técnica de Prova por Redução)
P  i  Lp ?
No entanto...
Nem sempre os problemas reais são questões de decisão.
São em geral solicitações para calcular ou transformar
alguma entrada.
Ex. A tarefa de um analisador sintático (parser) de um
compilador pode ser vista como um problema de decisão: a
cadeia de entrada (programa escrito numa linguagem de
programação X) é uma sentença da linguagem Lx, ou seja,
pertence ao conjunto dos programas válidos em X?
E a tarefa do compilador?
O compilador como um todo transforma um programa
escrito em código fonte em outro, em código objeto. Essa
tarefa está longe de responder simplesmente sim ou não
sobre a validade de um programa.
Exemplo
• Seja P1 o problema de compilar um programa na linguagem de
programação X. Quão difícil é resolvê-lo? (qual sua complexidade?).
• Considere agora o problema de decisão P2: dada uma cadeia, ela
pertence à linguagem de cadeias válidas na linguagem de
programação X - Lx? Ou seja, P2 corresponde ao parser dos
programas em X.
• Repare que P2 é parte da solução de P1.
• Se provarmos que é difícil resolver P2, então P1 não pode ser mais
fácil. Isto é, se é difícil a tarefa do parser, a do compilador não pode
ser mais fácil.
• Por contradição: se fosse fácil (eficiente) gerar código-objeto,
poderíamos usar o próprio compilador para, ao ter sucesso ao produzir
o código para um programa (cadeia), concluir que essa entrada se trata
de um elemento válido de Lx. Assim, contradizemos a suposição de
que testar a pertinência a Lx é difícil.
Assim, temos uma prova por contradição da afirmação:
Se o teste de pertinência a Lx é difícil, então compilar
programas na linguagem de programação X é difícil.
Essa técnica de redução é extremamente útil no estudo da
complexidade de problemas, e é facilitada pela noção de que
problemas são questões sobre pertinência a uma linguagem, e não
tipos mais gerais de questões.
Download