Aula 6 - A Maior Subsequência Comum Possível (Programação Dinâmica Parte IV)
Aplicações na Biologia Um problema bastante em voga na Biologia é a análise do DNA de dois ou mais organismos distintos. Um DNA é composto por uma sequência de moléculas, chamadas de bases, A Adenina T Timina C Citosina G Guanina Computacionalmente, um DNA pode ser visto como uma fita dupla de Strings, com o alfabeto {A,T,G,C}
Aplicações na Biologia
Aplicações na Biologia Dado os DNA s de dois organismos: S 1 = ACCGTGGAAAAGGTTAAGGCCAGGATTTAACCGCGGGC S 2 = ACCGCGGTTTAATCCGGATAGGTTGAAATGGTTGAAAC É possível indagar: Quão semelhantes são estes dois organismos? Estes organismos são da mesma espécie? Um destes organismos é ancestral do outro organismo? Observe que a resposta destas questões dependerão de quão semelhantes eles são.
Similaridade É possível medir similaridade de várias formas diferentes! É possível definir que duas fitas de DNA são similares se uma é uma substring da outra. Também é possível definir similaridade pelo número de transformações necessária para transforma uma fita de DNA na outra. Aqui, quanto menor o número de transformações maior a similaridade. Uma terceira forma é definir uma outra fita S 3 de tal forma que esta seja formada pelas bases que coincidentes nas fitas S 1 e S 2. Quanto maior for S 3 mais semelhantes serão S 1 e S 2. S 3 é a maior subsequência comum possível entre S 1 e S 2.
Subsequência Introdução Uma Subsequência Uma Subsequência Comum A subsequência comum mais longa Dada uma sequência X = x 1,x 2,...,x m e outra sequência Z = z 1,z 2,...,z k. A sequência Z será subsequência de X se existir uma sequência estritamente crescente i 1,i 2,...,i k de índices de X tal que para todo j = 1,2,...,k implique em x ij = z j. Por exemplo, dado X = A,B,C,B,D,A,B e Z = B,C,D,B. Z é uma subsequência de X com a sequência de índices correspondendo a 2,3,5,7
Subsequência Comum Uma Subsequência Uma Subsequência Comum A subsequência comum mais longa Agora são dadas duas sequências, X e Y. É dito que Z é uma subsequência comum de X e Y se Z é uma subsequência de X e de Y ao mesmo tempo. Por exemplo, e X = A,B,C,B,D,A,B Y = B,D,C,A,B,A note que a subsequência B,C,A, embora não seja a subsequência mais longa. A subsequência mais longa (LCS) terá comprimento 4: B,C,B,A ou B,D,A,B.
Definindo o Problema Uma Subsequência Uma Subsequência Comum A subsequência comum mais longa Problema da Subsequência Comum Mais Longa (LCS) Dadas duas sequências X = x 1,x 2,...,x m e Y = y 1,y 2,...,y n é desejado encontrar a maior subsequência de maior comprimento possível comum às sequências X e Y. Este problema pode ser abordado via programação dinâmica.
Passo 1: Caracterizando a Maior Subsequência Comum Por força bruta: Enumera-se todas as possíveis subsequências de X. Checa-se se cada uma destas subsequências também é subsequências de Y, guardando a de maior comprimento. Cada subsequência pode ser representada por por um subconjunto de índices na forma {1,2,...,m}. Observe que X terá 2 m subsequências, o que acarreta em um custo exponencial, sendo inviável na prática!
Passo 1: Caracterizando a Maior Subsequência Comum O problema LCS apresenta uma subestrutura ótima! Como será visto, a classe natural de subproblemas são os pares dos prefixos de duas sequências de entrada. Dada uma sequência X = x 1,x 2,...,x m Definie-se o i-ésimo prefixo de X, para i = 0,1,2,...,m como Por exemplo, dada a sequência X i = x 1,x 2,...,x i X = A,B,C,B,D,A,B então e X 0 = (sequência vazia) X 4 = A,B,C,B
Passo 1: Caracterizando a Maior Subsequência Comum Teorema 15.1 - Ótima para o Problema LCS Faça X = x 1,x 2,...,x m e Y = y 1,y 2,...,y n serem sequências, e faça Z = z 1,z 2,...,z k ser uma LCS de X e Y. 1 Se x m = y n, então z k = x m = y n e Z k 1 é uma LCS de X m 1 e Y n 1. 2 Se x m y n, então z k x m implicando que Z é uma LCS de X m 1 e de Y. 3 Se x m y n, então z k y n implicando que Z é uma LCS de X e de Y n 1.
Passo 1: Caracterizando a Maior Subsequência Comum Prova do Teorema 15.1 1 Se z k x m e fixarmos x m = y n para obtermos Z com uma LCS de X e Y de comprimento k +1, estaremos contrariando o fato de Z ser uma LCS de X e Y. Assim, temos que ter z k = x m = y n. Observe então que o prefixo Z k 1 de comprimento k 1 é uma sequência comum de X m 1 e Y n 1. Pergunta-se Z k 1 é uma LCS? Suponha que existe uma sequência comum W de X m 1 e Y n 1 com comprimento maior que k 1. Logo fazendo x m = y n implicaria que W teria um comprimento maior que k, o que seria uma contradição.
Passo 1: Caracterizando a Maior Subsequência Comum Prova do Teorema 15.1 2 Se z k x m então Z é uma sequência comum entre X m 1 e Y. Se existisse uma sequência comum W de X m 1 e Y com comprimento maior que k, então W também poderia ser uma sequência comum de X m e Y, contrariando a suposição de que Z é uma LCS de X e Y. 3 Uma prova simétrica ao item 2.
Passo 2: Uma Solução Recursiva O Teorema 5.1 afirma que deve-se observar 1 ou 2 subproblemas para se encontrar uma LCS de X = x 1,x 2,...,x m e Y = y 1,y 2,...,y n, Se x m = y n deve-se procurar a LCS de X m 1 e Y n 1 e depois acrescentar x m = y n. Se x m y n, então deve-se resolver 2 subproblemas: Encontrar uma LCS de X m 1 e Y; e Encontrar uma LCS de X e Y n 1 Sendo a LCS mais longa destas duas a LCS de X e Y. Desta forma a sobreposição nas soluções dos subproblemas é clara! Para resolver a LCS de X e Y é necessário resolver a LCS de X m 1 e Y, e X e Y n 1.
Passo 2: Uma Solução Recursiva Defina c[i,j] ser o comprimento de uma LCS das sequências X i e Y j. Se i = 0 ou j = 0, uma das sequências tem comprimento zero, implicando que a LCS tem comprimento zero. ótima do problema da LCS e a forma recursiva: 0, sei = 0 ou j = 0 c[i,j] = c[i 1,j 1]+1, sei,j > 0 e x i = y j max(c[i,j 1],c[i 1,j]), sei,j > 0 e x i y j (1)
Passo 3: Computando o comprimento de uma LCS Um algoritmo natural para resolver a Equação 1 teria custo exponencial! Contudo este problema tem apenas Θ(nm) subproblemas distintos. Algoritmo com programação dinâmica: Considere duas sequências como entrada, X = x 1,x 2,...,x m e Y = y 1,y 2,...,y n Os valore c[i, j] são armazenados em uma tabela c[0..m, 0..n], onde os valores são computados linha a linha, esquerda para direita Também há uma tabela b[1..m, 1..n] tal que são armazenados as entradas para a escolha da solução ótima dos subproblemas quando está se computando c[i, j]. Saídas: b e c, onde c[m,n] contem o comprimento de uma LCS de X e Y.
Passo 3: Computando o comprimento de uma LCS LCS-LENGTH(X,Y) 1 m = X.length 2 n = Y.length 3 let b[1..n,1..n] e c[0..m,0..n] be new tables 4 for i = 1 to m 5 c[i,0] = 0 6 for i = 1 to n 7 c[0,j] = 0 8 for i = 1 to m 9 for j = i to n 10 if x i == y j 11 c[i,j] = c[i 1,j 1]+1 12 b[i,j] = տ 13 elseif c[i 1,j] c[i,j 1] 14 c[i,j] = c[i 1,j] 15 b[i,j] = 16 else c[i,j] = c[i,j 1] 15 b[i,j] = 17 return c and b
Passo 3: Computando o comprimento de uma LCS Exemplo: Dadas as sequências X = A,B,C,D,A,B e Y = B,D,C,A,B,A. Observe que o custo será Θ(nm) visto que a referência a cada entrada de uma tabela tem custo de Θ(1).
Passo 4: Construindo uma LCS Observando a tabela b gerada pelo LCS-LENGTH rapidamente é possível se construir uma LCS das sequências X e Y. Começa-se na entrada b[n, m], e segue-se as setas. Quando encontra-se a seta տ em b[i,j] significa que x i = y j, logo este é um elemento da LCS. Assim, é possível se computar os elementos de uma LCS em ordem reversa.
Passo 4: Construindo uma LCS Para se imprimir a LCS na ordem correta, PRINT-LCS(b,X,i,j) 1 if i == 0 or j == 0 2 return // LCS is empty 3 if b[i,j] == տ 4 PRINT-LCS(b,X,i 1,j 1) 5 print x i 6 elseif b[i,j] == 7 PRINT-LCS(b,X,i 1,j) 8 else PRINT-LCS(b,X,i,j 1) Sendo a chamada inicial PRINT-LCS(b, X, X.length, Y.length).
Passo 4: Construindo uma LCS Para a tabela b gerada no nosso último exemplo, PRINT-LCS iria gerar a sequência, BCBA O custo para este procedimento será de O(m+n) Visto que este decrementa no mínimo uma unidade de i e/ou j para cada chamada recursiva.
Melhorando o Código! Observe que este código LENGTH-LCS pode ser melhorado em desempenho tanto no tempo como no espaço. Como? Exercício para reflexão! Será que a tabela b é realmente necessária? Será que a tabela c necessita ser totalmente armazenada?
Sugestão de Leitura Capítulo 15, seção 15.4 do ĺıvro do Cormen; Weiss, Mark Allen. Data Structures and Algorithms Analysis in C. Second Edition. (1997) - Capítulo 8