1.5 Algoritmos Fundamentais
1.5.4 Algoritmo de Programa¸ c˜ ao Dinˆ amica
Dada uma entrada para um problema que satisfa¸ca as duas propriedades acima, um al-goritmo baseado noparadigma de programa¸c˜ao dinˆamica opera resolvendo progressivamente subproblemas do problema original (geralmente, em ordem crescente de tamanho dos sub-problemas) e armazenando as solu¸c˜oes de cada subproblema em uma tabela para um poss´ıvel uso posterior. A id´eia ´e evitar que algum subproblema seja resolvido (desnecessariamente) mais de uma vez. Uma interpreta¸c˜ao alternativa de um algoritmo de programa¸c˜ao dinˆamica pode ser como uma maneira de executar os passos de um algoritmo recursivo em uma ordem conveniente, usando uma tabela para manter as solu¸c˜oes dos subproblemas j´a resolvidos por chamadas recursivas do algoritmo.
Por exemplo, no caso do Problema APS, um algoritmo de programa¸c˜ao dinˆamica pode ser interpretado como uma ordena¸c˜ao adequada dos passos do Algoritmo Alinha-Rec de forma que os alinhamentos obtidos por cada chamada recursiva (como, por exemplo, Alinha-Rec(s[1 . . 3], t[1 . . 4])) sejam armazenados em uma tabela.
Ao longo de um algoritmo de programa¸c˜ao dinˆamica, tentam-se estender solu¸c˜oes ´otimas de subproblemas a uma solu¸c˜ao ´otima de um subproblema maior, fazendo uso da Propri-edade das Subsolu¸c˜oes ´Otimas, e prosseguindo at´e que uma solu¸c˜ao ´otima do problema original seja encontrada.
Um algoritmo de programa¸c˜ao dinˆamica para o Problema APS foi publicado em 1970 por Needleman e Wunsch [NW70], embora haja relatos de que suas id´eias principais fizessem parte do folclore dos pesquisadores da ´epoca. O algoritmo, muito modificado desde ent˜ao por v´arios pesquisadores, foi melhorado em rela¸c˜ao `a complexidade de tempo e de espa¸co [Hir75]
e tamb´em adaptado para outros problemas, sendo que uma das adapta¸c˜oes mais importantes e populares ´e a desenvolvida por Smith e Waterman em 1981, para computar alinhamentos locais [SW81]. O algoritmo que veremos possui sua origem incerta e foi provavelmente descoberto independentemente por diversos pesquisadores [SM97].
1.5.4.1 Etapas do Algoritmo
Bem como v´arios algoritmos de programa¸c˜ao dinˆamica, o algoritmo de programa¸c˜ao dinˆamica para o Problema APS opera em duas etapas. Na primeira etapa, a distˆancia entre as seq¨uˆencias de entrada ´e calculada e, na segunda, um alinhamento ´otimo (i.e., de pontua¸c˜ao igual `a distˆancia entre as seq¨uˆencias) ´e determinado. Vamos `a descri¸c˜ao de cada etapa. Para nossas considera¸c˜oes, supomos que o alfabeto Σ e que a matriz de pontua¸c˜ao c estejam fixados, como no enunciado do Problema APS.
1.5.4.1.1 Etapa 1: C´alculo da Distˆancia Na primeira etapa, para seq¨uˆencias s e t de comprimentos|s|=me |t|=n, uma matrizade dimens˜oes (m+ 1)×(n+ 1), indexada por {0, . . . , m} e {0, . . . , n}, ´e preenchida com as pontua¸c˜oes de alinhamentos ´otimos de prefixos descom prefixos det, de forma que a posi¸c˜ao (i, j) deacontenha a pontua¸c˜ao de um alinhamento ´otimo des[1 . .i] et[1 . .j], isto ´e, de modo quea[i, j] =d(s[1 . .i], t[1 . .j]), para 0≤i≤m e 0≤j ≤n. ´E claro que a distˆancia d(s, t) =d(s[1 . .m], t[1 . .n]) est´a na posi¸c˜ao a[m, n].
Conforme mencionamos, o algoritmo tenta “estender” solu¸c˜oes j´a calculadas para pro-blemas de maior tamanho (ele opera “de baixo para cima”).
Pela defini¸c˜ao da matriz a, a linha i = 0 ´e tal que a[0, j] = d(s[1 . . 0], t[1 . .j]) = d(ε, t[1 . .j]), para 0≤j ≤n. Como os alinhamentos que consideramos s˜ao livres de colunas em branco, a ´unica possibilidade de um alinhamento entre a seq¨uˆencia vazia e t[1 . .j] ´e o alinhamento em que cada caractere de t[1 . .j] fica alinhado a um espa¸co. Naturalmente, como este alinhamento ´e ´unico, ele ´e trivialmente um alinhamento ´otimo e seu custo ´e a[0, j] =Pj
k=1c( , t[k]). Em outras palavras, temos quea[0, j] =a[0, j−1] +c( , t[j]), para todo j= 1, . . . , n e a[0,0] = 0. Essa ´e a forma de preenchimento da linha i= 0 da matriz.
O mesmo argumento vale para ver que a coluna j = 0 deve ser preenchida de acordo com a rela¸c˜ao de recorrˆencia a[i,0] =a[i−1,0] +c(s[i], ), para todoi= 1, . . . , m.
Naturalmente, como h´a apenas 3 possibilidades para a ´ultima coluna de um alinhamento e o Problema APS satisfaz `a Propriedade das Subsolu¸c˜oes ´Otimas, sabemos que um alinha-mento ´otimo entre s[1 . .i] et[1 . .j] pode ser obtido a partir de um alinhamento ´otimo de s[1 . .i−1] e t[1 . .j] justaposto com s[i]
ou de um alinhamento ´otimo de s[1 . .i−1] e t[1 . .j−1] justaposto com s[i]t[j]
ou de um alinhamento ´otimo des[1 . .i] e t[1 . .j−1] jus-taposto com t[j]
, dependendo de qual possuir a menor pontua¸c˜ao. Em termos da matriz a, isso fica:
a[i, j] = min
a[i−1, j] +c(s[i], ), a[i−1, j−1] +c(s[i], t[j]),
a[i, j−1] +c( , t[j])
, (1.3)
parai >0 ej >0.
Para preenchermos a matrizacom o algoritmo, devemos escolher uma ordem conveniente para que o c´alculo dea[i, j] seja feito apenas ap´osa[i−1, j],a[i−1, j−1] ea[i, j−1] estarem definidos. Uma possibilidade para isso ´e preencher a matrizalinha a linha, a partir da linha de ´ındice 0 e, para cadaifixado, em ordem de j crescente4.
Um algoritmo que implementa as id´eias acima ´e o AlgoritmoDist.
Como um coment´ario a parte, algumas implementa¸c˜oes do Algoritmo Dist s˜ao feitas com a suposi¸c˜ao de que existe uma constante g tal que c( , σ) = g para todo σ ∈ Σ. Em
4Outra possibilidade para preenchimento dea´e fazer os c´alculos coluna a coluna, a partir da coluna 0 e, parajfixado, fazer o preenchimento comivariando de 0 am.
1.5 Algoritmos Fundamentais 15
a[i−1, j−1] a[i−1, j]
a[i, j−1]oo a[i, j]
ggOOOOOOOOOOOO OO
Figura 1.4: Para preencher a entradaa[i, j], o AlgoritmoDistprecisa de 3 outras entradas:
a[i−1, j],a[i−1, j−1] e a[i, j−1].
Algoritmo 1.2Dist(s, t)
Entrada: Duas seq¨uˆenciasse t, com|s|=me |t|=n.
Sa´ıda: Uma matriza= (aij) coma[i, j] =d(s[1 . .i], t[1 . .j]).
1: m← |s|;n← |t|;a[0,0]←0;
2: para j= 1, . . . , n fa¸ca
3: a[0, j]←a[0, j−1] +c( , t[j]);
4: para i= 1, . . . , m fa¸ca
5: a[i,0]←a[i−1,0] +c(s[i], );
6: paraj = 1, . . . , n fa¸ca
7: a[i, j]←a[i−1, j] +c(s[i], );
8: se a[i, j]> a[i−1, j−1] +c(s[i], t[j])ent˜ao
9: a[i, j]←a[i−1, j−1] +c(s[i], t[j]);
10: se a[i, j]> a[i, j−1] +c( , t[j])ent˜ao
11: a[i, j]←a[i, j−1] +c( , t[j]);
12: Devolvaa;
particular, nesse caso, a primeira linha de a pode ser preenchida com a[0, j] = g·j e, a primeira coluna, coma[i,0] =g·i. ´E comum referir-se a uma tal matriz de pontua¸c˜ao como matriz de custos lineares para lacunas.
1.5.4.1.2 Etapa 2: C´alculo de um Alinhamento ´Otimo At´e aqui, apenas o c´alculo da pontua¸c˜ao de um alinhamento ´otimo (distˆancia entre seq¨uˆencias) foi efetuado. Terminado esse pr´e-processamento, podemos usar a tabelaaresultante da primeira etapa para construir os alinhamentos ´otimos.
A constru¸c˜ao de um alinhamento ´otimo ´e feita observando-se qual (ou quais, se esti-vermos interessados em v´arios alinhamentos ´otimos) das pontua¸c˜oes dentre a[m −1, n], a[m−1, n−1] e a[m, n−1] produziu a pontua¸c˜ao a[m, n] (correspondente `a pontua¸c˜ao
´
otima de todos os m caracteres de s alinhados a todos os n caracteres de t) e decidindo, portanto, qual ´e a ´ultima coluna de um alinhamento ´otimo.
Desta forma, supondo-se quea[m0, n0] seja a posi¸c˜ao dentre as trˆes descritas que produziu a pontua¸c˜aoa[m, n], podemos obter as demais colunas do alinhamento repetindo o processo, usando (m0, n0) no lugar de (m, n) e repetir o procedimento de procura de que posi¸c˜ao deu origem a m0 e n0 at´e que a posi¸c˜ao (0,0) de a seja atingida, momento em que todas as colunas do alinhamento estar˜ao determinadas.
O Algoritmo Alinhacont´em um resumo dessa discuss˜ao.
Algoritmo 1.3Alinha(a, s, t)
Entrada: Duas seq¨uˆenciasse te a matrizadevolvida por Dist(s, t).
Sa´ıda: Um alinhamento entre set de pontua¸c˜ao m´ınima.
1: m← |s|;n← |t|;
2: sem= 0 ent˜ao
3: Devolva os caracteres detalinhados a espa¸cos ems;
4: sen= 0 ent˜ao
5: Devolva os caracteres desalinhados a espa¸cos em t;
6: sea[m, n] =a[m−1, n] +c(s[m], ) ent˜ao
7: Devolva
Alinha(a, s[1 . .m−1], t) : s[m]
8: sea[m, n] =a[m−1, n−1] +c(s[m], t[n])ent˜ao
9: Devolva
Alinha(a, s[1 . .m−1], t[1 . .n−1]) : s[m]t[n]
10: sea[m, n] =a[m, n−1] +c( , t[n]) ent˜ao
11: Devolva
Alinha(a, s, t[1 . .n−1]) : t[n]
1.5.4.2 An´alise de Complexidade
Vamos analisar a complexidade de tempo e de espa¸co dos algoritmos vistos. Para evitar ambig¨uidade, convencionamos que, nesta se¸c˜ao, a palavra espa¸co ser´a utilizada para nos referirmos `a quantidade de mem´oria requerida para os algoritmos em vez de designar o caractere espa¸co ( ) como nas demais se¸c˜oes.
O AlgoritmoDistinicializa a primeira linha da matrizaem tempoO(n) (linhas 2 e 3).
A linha 1 ´e executada em tempoO(1). Ap´os a inicializa¸c˜ao, os la¸cos encaixados emie em j (linhas 4–11) s˜ao executados. A parte mais interna desses la¸cos (i.e., cada execu¸c˜ao das linhas 7–11) leva tempo constante e s˜ao realizadas um total de O(mn) itera¸c˜oes. Ao longo do algoritmo, a linha 5 ´e executada um total de m vezes e, como cada execu¸c˜ao dela toma tempo constante, a parcela de tempo total do algoritmo referente a sua execu¸c˜ao ´e O(m).
Disso podemos concluir que o algoritmo leva tempoO(1)+O(n)+O(m)+O(mn) =O(mn).
O espa¸co usado pelo algoritmo5´eO(1), uma vez que os recursos de mem´oria empregados s˜ao, basicamente, as vari´aveis de controle do algoritmo (que s˜ao i,j,m en) e que ocupam espa¸coO(1), a matriz de pontua¸c˜aoc, que tem tamb´em tamanhoO(1) (pois o alfabeto est´a fixado) e a matriza, de tamanho (m+ 1)×(n+ 1), que faz parte da resposta devolvida por Dist.
O outro algoritmo, Alinha, opera em tempo e espa¸co lineares no tamanho das seq¨uˆ en-cias s e t. Para nos convencermos da complexidade de tempo, basta ver que cada coluna do alinhamento constru´ıdo como solu¸c˜ao requer que, no m´aximo, 3 posi¸c˜oes da matriz a sejam analisadas (vide linhas 6–11). Como cada um dos testes ´e feito em tempo constante, a determina¸c˜ao de uma coluna qualquer do alinhamento final toma tempoO(1). Ademais, todos os alinhamentos que consideramos (i.e., livres de colunas em branco) possuem com-primento m´aximo dem+ncolunas. Da´ı, conclu´ımos que o AlgoritmoAlinhaleva tempo O(m+n).
Para o espa¸co usado pelo AlgoritmoAlinha, observemos que, excetuando-se a matriza
5Para a an´alise de espa¸co de nossos algoritmos, usamos a pr´atica comum [Pap94] de n˜ao considerar na complexidade o espa¸co usado para resposta dos algoritmos (i.e., os algoritmos s˜ao modelados comom´aquinas de Turing de Entrada e Sa´ıda).
1.5 Algoritmos Fundamentais 17
e o alinhamento produzido como resposta (que usa espa¸coO(m+n)), tudo o que ´e necess´ario
´
e armazenar as vari´aveis de controle do algoritmo que totalizam espa¸co O(1) e a pilha de recurs˜ao do algoritmo, que tem tamanhoO(m+n) (porque uma chamada recursiva ´e feita para determinar cada coluna do alinhamento). Isso justifica a afirma¸c˜ao de o Algoritmo Alinhausar espa¸co O(m+n).
E importante ver que, apesar de ambos os Algoritmos´ Dist e Alinha terem comple-xidades individuais de espa¸co de O(1) e O(m+n), respectivamente, uma implementa¸c˜ao natural para encontrar um alinhamento ´otimo desetopera primeiro fazendo uma chamada a Dist, depois armazenandoa e, por fim, fazendo uma chamada aAlinha, de forma que este m´etodo usa espa¸co O(mn) como um todo.
Como um coment´ario adicional, embora tenhamos descrito algoritmos para o Problema APS usando espa¸co (total) quadr´atico, ´e poss´ıvel realizar todo o procedimento em espa¸co O(m+n), mantendo ainda a complexidade de tempo assint´otica de O(mn), conforme ve-remos na Se¸c˜ao 1.6.