distancia de edição

of 27 /27
                           

Embed Size (px)

Transcript of distancia de edição

Universidade Federal de Minas Gerais Departamento de Cincia da Computao

Pro jeto e Anlise de Algoritmos

Trabalho Prtico II disponvel em: http://www.dcc.ufmg.br/denis/paa/denis-paa06tp2.pdf Cdigo fonte disponvel em: http://www.dcc.ufmg.br/denis/paa/denis-paa06tp2.tar.gz

Denis Pinto PinheiroMonitor: Fabiano C. Botelho Professor: Nivio Ziviani

Belo Horizonte 2 de maio de 2006

Sumrio1 Distncia de Edio

1.1 1.2 1.3 1.4

Algoritmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Complexidade de Tempo e Espao . . . . . . . . . . . . . . . . . . . . Implementao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemplo Prtico . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1

1 2 2 5

2

Conjunto Independente de Vrtices

2.1 Soluo tima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.2 Reduo do Clique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.3 Algoritmo Aproximado . . . . . . . . . . . . . . . . . . . . . . . . . . 96 11 14

A Cdigo Fonte do algoritmo de D.E. B

B.1 Arquivo cabealho B.2 Programa

Cdigo Fonte da implementao do Grafografomatriz.h

grafomatriz.c

. . . . . . . . . . . . . . . . . . . . . 14 . . . . . . . . . . . . . . . . . . . . . . . . . 1518

C

Cdigo Fonte dos Algoritmos para o PCI

2

1

Distncia de Edio

O algoritmo a seguir til para ser usado em corretores ortogrcos. Sejam dadas duas cadeias de caracteres: X = x , x , ..., x e Y = y , y , ..., y . O nmero k de operaes de substituio, insero e retirada de caracteres necessrio para transformar X em Y conhecido como distncia de edio. Assim, a distncia de edio de ed(X,Y) corresponde ao nmero k de operaes necessrias para converter X em Y . Por exemplo, se X = matranda e Y = saturadas ento ed(XY)=4. A sequncia de operaes : (i) substitui x por y ('s'), (ii) insere y ('u') aps x , (iii) retira x ('n') e (iv) insere y ('s') aps x .1 2 m 1 2 n 1 1 4 3 6 9 8

1.1

A Distncia de Edio (Levenshtein, 1965) entre dois "strings"(duas sequncias de caracteres) dada pelo nmero mnimo de operaes necessrias para transformar um string no outro. Entendemos por "operaes"a insero, deleo ou substituio de um carcter. muito til para aplicaes que precisam determinar quo semelhantes dois strings so, como por exemplo o caso com os vericadores ortogrcos. A Programao Dinmica (PD) um mtodo para a construo de algoritmos para a resoluo de problemas computacionais, em especial os de otimizao combinatria. A PD aplicvel a problemas onde a soluo tima pode ser computada a partir da soluo tima previamente calculada e memorizada - de forma a evitar reclculo de outros subproblemas que, sobrepostos, compem o problema original [5, 2]. O Algoritmo 1 apresenta uma soluo que usa programao dinmica para resolver o problema da distncia de edio, encontrado em [3]: O algoritmo recebe como entrada dois strings str1 e str2 de tamanhos m e n, respectivamente. Primeiramente, inicializa-se uma matriz D , onde sero armazenados os custos de edio do string str1 no string str2 (linha 2). Os dois primeiros inicializam a primeira linha e a primeira coluna de D com os ndices i e j das mesmas (linhas 4 a 9). Da linha 10 a 19, os aninhados percorrem a matriz D, armazenando em D[i][j] o custo de transformar str1[1..i] em str2[1..j] (linha 18). A cada passo, D[i][j] recebe o menor custo entre os seguintes casos: se possvel transformar str1[1..i] a str2[1..j1] em k operaes, ento pode-se simplesmente adicionar str[j] depois para obter str2[1..j] em k + 1 operaes; se possvel transformar str1[1..i 1] a str2[1..j] em k operaes, ento podese fazer as mesmas operaes em str1[1..i] e depois remover o str1[i] original ao m de k + 1 operaes. se possvel transformar str1[1..i 1] a str2[1..j 1] em k operaes, ento pode-se fazer o mesmo com str1[1..i] se str1[i] for igual a str2[j], caso contrrio, faz-se uma substituio de str2[j] por str1[i], requerindo k + 1 operaes no nal para transformar str1[1..i] a str2[1..j].(m+1)(n+1)loops loops

Algoritmo

Programao Dinmica

1

Algoritmo 1

1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:

DistanciaEdicao char

D = int i, j, t for i = 0 at m D[i][0] = iint int

;

Algoritmo para calcular a Distncia de Edio. ( str1[1..m], str2[1..n]) [0..m][0..n];char

end for for

;

do

j = 0 at n D[0][j] = j

end for for

;

do

i = 1 at i NumVertices && ListaVazia) { if (Grafo->Mat[*Vertice][Aux] > 0) ListaVazia = FALSE; else Aux++; } return (ListaVazia == TRUE); } /* ListaAdjVazia */ Pointer PrimeiroListaAdj(TipoValorVertice *Vertice, TipoGrafo *Grafo) { TipoValorVertice Result; Pointer Aux = 0; short ListaVazia = TRUE; while (Aux < Grafo->NumVertices && ListaVazia) { if (Grafo->Mat[*Vertice][Aux] > 0) { Result = Aux; ListaVazia = FALSE; } else Aux++; } if (Aux == Grafo->NumVertices) printf("Erro: Lista adjacencia vazia (PrimeiroListaAdj)\n"); return Result; } /* PrimeiroListaAdj */ void ProxAdj(TipoValorVertice *Vertice, TipoGrafo *Grafo, TipoValorVertice *Adj, TipoPeso *Peso, Pointer *Prox, short *FimListaAdj) { /* --Retorna Adj apontado por Prox--*/ *Adj = *Prox; *Peso = Grafo->Mat[*Vertice][*Prox]; (*Prox)++; while (*Prox < Grafo->NumVertices && Grafo->Mat[*Vertice][*Prox] == 0) (*Prox)++; if (*Prox == Grafo->NumVertices) *FimListaAdj = TRUE; } /* ProxAdj- */ void RetiraAresta(TipoValorVertice *V1, TipoValorVertice *V2, TipoPeso *Peso, TipoGrafo *Grafo) { if (Grafo->Mat[*V1][*V2] == 0)

16

printf("Aresta nao existe\n"); else { *Peso = Grafo->Mat[*V1][*V2]; Grafo->Mat[*V1][*V2] = 0; } } /* RetiraAresta */ void LiberaGrafo(TipoGrafo *Grafo) { /* Nao faz nada no caso de matrizes de adjacencia */ } /* LiberaGrafo */ void ImprimeGrafo(TipoGrafo *Grafo) { short i, j; printf(" "); for (i = 0; i NumVertices - 1; i++) printf("%3d", i); printf("\n"); for (i = 0; i NumVertices - 1; i++) { printf("%3d", i); for (j = 0; j NumVertices - 1; j++) printf("%3d", Grafo->Mat[i][j]); printf("\n");

} } /* ImprimeGrafo */

void GrafoTransposto(TipoGrafo *Grafo, TipoGrafo *GrafoT) { TipoValorVertice v, Adj; TipoPeso Peso; Pointer Aux; FGVazio(GrafoT); GrafoT->NumVertices = Grafo->NumVertices; GrafoT->NumArestas = Grafo->NumArestas; for (v = 0; v NumVertices - 1; v++) { if (!ListaAdjVazia(&v, Grafo)) { Aux = PrimeiroListaAdj(&v, Grafo); FimListaAdj = FALSE; while (!FimListaAdj) { ProxAdj(&v, Grafo, &Adj, &Peso, &Aux, &FimListaAdj); InsereAresta(&Adj, &v, &Peso, GrafoT); } } } } /* GrafoTransposto */ /* End. */

17

C

Cdigo Fonte dos Algoritmos para o PCI

A seguir apresentado o cdigo fonte do arquivo moduleindep.c que contem o algoritmo que encontra a soluo tima para o PCI (funo CIndepFB ), o algoritmo de reduo do Clique para o CI (funo CliqueRedCIndep ) e o que encontra a soluo aproximada para o PCI(funo Ramsey e CliqueRemoval ).

#include #include "moduleindep.h" #include "grafomatriz.h" /* Algoritmo Fora Bruta para o PCI */ /* BEGIN PCIFB*/ short isCIndep(TipoGrafo *G, int *S, int k) { short hasAdj = FALSE; int i, j; for(i = 1; i l_max && isCIndep(G, S, k)) { for(i = 1; i NumVertices; p = 1; /* Para todo u,v em V */ for(u = 0; u < _G.NumVertices; u++) { for(v = 0; v < _G.NumVertices; v++) {

19

/* Se (u!=v) e (u,v) nao esta em A */ if(u != v) && (!ExisteAresta(u, v, G)) { /* _A = _A + (u,v) */ InsereAresta(&u, &v, &p, &_G);

}

}

}

}

// solucao do CI = solucao do Clique CIndepFB(&_G);

/* End REDUCAO */ /********************************************************\ Algoritmo aproximado \********************************************************/ /*Begin APPRX */ void print_V(short *S, int n) { int i, j; for(i = 0; i < n; i++) { if(S[i]) { fprintf(stdout, "%d ", i); fprintf(stderr, "%d ", i); } } } short vazio_V(short *V, short n) { int v; for(v = 0; v < n; v++) { if(V[v]) return FALSE; } return TRUE; } short* putv_V(TipoValorVertice v, short *V) { V[v] = 1; return V; } short* larger_of(short *V1, short *V2, int n) { int i, s1, s2; s1 = s2 = 0;

20

}

for(i = 0; i < n; i++) { s1 += V1[i]; s2 += V2[i]; } return ((s1 > s2) ? V1 : V2);

short* neigh_V( TipoGrafo *G, TipoValorVertice v, short* V) { short *_V; int u; _V = (short *)malloc(sizeof(short)*G->NumVertices); for(u = 0; u < G->NumVertices; u++) { _V[u] = ((u != v) && V[u] && ExisteAresta(v, u, G)) ? 1 : 0; } return _V;

}

short* non_neigh_V( TipoGrafo *G, TipoValorVertice v, short* V) { short *_V; int u; _V = (short *)malloc(sizeof(short)*G->NumVertices); for(u = 0; u < G->NumVertices; u++) { _V[u] = ((u == v) || !V[u] || ExisteAresta(v, u, G)) ? 0 : 1; } return _V;

}

void non_N(TipoGrafo *G, TipoValorVertice v, short *V) { int u, n; n = G->NumVertices; for(u = 0; u < n; u++) { V[u] = ((u == v) || (!V[u] || ExisteAresta(v, u, G))) ? 0 : 1; }

}

TipoValorVertice choose_v(short *V, int N) { struct timeval t; /* escolhe aleatoriamente um vertice em V */ TipoValorVertice v = 0;

21

gettimeofday(&t,NULL); srand((unsigned int)t.tv_usec); v = } (int) rand() % N;

return v;

short** Ramsey_V(TipoGrafo *G, short *V) { TipoValorVertice v; short **CI, **CI1, **CI2; int n; n = G->NumVertices; CI = (short **) malloc(2 * sizeof(short*)); if(vazio_V(V, n)) { CI = (short **) malloc(2 * sizeof(short*)); CI[0] = (short *) malloc(n * sizeof(short*)); CI[1] = (short *) malloc(n * sizeof(short*)); return CI; } v = choose_v(V,n); CI1 = Ramsey_V(G, neigh_V(G, v, V)); CI2 = Ramsey_V(G, non_neigh_V(G, v, V)); CI[0] = larger_of(putv_V(v, CI1[0]), CI2[0], n); CI[1] = larger_of(CI1[1], putv_V(v, CI2[1]), n); return CI;

}

void Ramsey(TipoGrafo *G) { short *V, **CI; int i; V = (short *) malloc(sizeof(short) * G->NumVertices); for(i = 0; i < G->NumVertices; i++) { V[i] = 1; } CI = Ramsey_V(G, V); } print_V(CI[1], G->NumVertices);

22

void remove_clique(TipoGrafo *G, short **CI, short *V) { int v; for(v = 0; v < G->NumVertices; v++) { if(CI[0][v] && V[v]) V[v] = 0; }

}

void CliqueRemoval(TipoGrafo *G) { short *IS, **CIi; short *V; int i; V = (short *)calloc(G->NumVertices, sizeof(short)); for(i = 0; iNumVertices; i++) { V[i] = 1; } CIi = Ramsey_V(G,V); while(!vazio_V(V, G->NumVertices)) { remove_clique(G, CIi, V); IS = larger_of(CIi[1], IS, G->NumVertices); CIi = Ramsey_V(G,V); } print_V(IS, G->NumVertices);

}

/* Begin APPRX */ void geraSaidaIndep(FILE * ArqAval) { /* Processa o arquivo ArqAval de alguma forma */ TipoGrafo G; int n, u, v, p; fscanf(ArqAval, "%d\n", &n); G.NumVertices = n; G.NumArestas = 0; p = 1; FGVazio(&G); while(!feof(ArqAval)) { fscanf(ArqAval, "%d %d\n", &u, &v); G.NumArestas++; InsereAresta(&u, &v, &p, &G); /* 1 chamada g-direcionado */ InsereAresta(&v, &u, &p, &G); /* 2 chamadas g-naodirecionado */ } /* Gera a saida */ CIndepFB(&G);

23

fprintf(stdout, "\n"); /*CliqueRedCIndep(&G); fprintf(stdout, "\n");*/ /*GredyIS(&G); fprintf(stdout, "\n"); fprintf(stderr, "\n");*/ /*Ramsey(&G); fprintf(stdout, "\n"); fprintf(stderr, "\n"); */ /*CliqueRemoval(&G); fprintf(stdout, "\n"); fprintf(stderr, "\n");*/

}

Referncias

[1] Ravi Boppana and Magns M. Halldrson. Approximating maximum independent sets by expluding subgraphs. SWAT 90 2nd Scandinavian Workshop on Algorithm Teory, 447:1325, 1990. [2] Thomas H. Cormen et. al. edition, 2002. [3] Dan Goseld. 1997.Algoritmos: Teoria e Prtica

. Campus, Rio de Janeiro, 2nd . Cambridge Univercity Press,

Algorithms on strings, trees and sequences

[4] Magns M. Halldrson. Approximating maximum independent sets in graphs. In Springer-Verlag, editor, In APROX '98: Proccedings of the International Workshop on Approximating Algorithms for Combinatorial Optimization, pages 113, London, UK, 1998. [5] Nivio Ziviani. Projeto de Algoritmos So Paulo, 2nd edition, 2004.com implementaes em Pascal e C

. Thomson,

24