CCO 101 PROCESSAMENTO DE DADOS

46
CIC 111 Análise e Projeto de Análise e Projeto de Algoritmos II Algoritmos II Universidade Federal de Itajubá Prof. Roberto Affonso da Costa Junior

Transcript of CCO 101 PROCESSAMENTO DE DADOS

Page 1: CCO 101 PROCESSAMENTO DE DADOS

CIC 111Análise e Projeto de Análise e Projeto de

Algoritmos IIAlgoritmos II

Universidade Federal de Itajubá

Prof. Roberto Affonso da Costa Junior

Page 2: CCO 101 PROCESSAMENTO DE DADOS

AULA 16AULA 16

– Directed graphs• Topological sorting• Dynamic programming• Successor paths • Cycle detection

Page 3: CCO 101 PROCESSAMENTO DE DADOS

Directed GraphsDirected Graphs

Nesta aula, vamos estudar duas classes de grafos direcionados:

Grafos Acíclicos: não há ciclos no gráfico, portanto, não há nenhum caminho de nenhum nó para ele próprio1.

Grafos Sucessores: o grau de saída de cada nó é 1, então cada nó possui um sucessor único.

Acontece que em ambos os casos, podemos ter algoritmos eficientes baseados nas propriedades especiais dos grafos.1Os grafos acíclicos direcionados às vezes são chamados DAGs

Page 4: CCO 101 PROCESSAMENTO DE DADOS

Topological sortingTopological sorting

Uma ordenação topológico é uma ordenação dos nós de um grafo direcionado, de modo que, se houver um caminho do nó a para o nó b, o nó a aparece antes do nó b no pedido. Por exemplo, para o grafo

uma ordenação topológico é [4, 1, 5, 2, 3, 6]:

1 3

4 5 6

1 3

4 5 6

4 1 34 5 6

Page 6: CCO 101 PROCESSAMENTO DE DADOS

AlgoritmoAlgoritmo

A ideia é passar pelos nós do grafo e sempre começar por uma busca em profundidade do nó atual, que ainda não tiver sido processado. Durante as pesquisas, os nós possuem três estados possíveis:Estado 0: o nó não foi processado (branco)Estado 1: o nó está em processamento (cinza claro)Estado 2: o nó foi processado (cinza escuro)

Inicialmente, o estado de cada nó é 0. Quando uma pesquisa atinge um nó pela primeira vez, seu estado se torna 1. Finalmente, depois de todos os sucessores do nó terem sido processados, seu estado se torna 2.

Page 7: CCO 101 PROCESSAMENTO DE DADOS

AlgoritmoAlgoritmo

Se o grafo contiver um ciclo, descobriremos isso durante a pesquisa, porque, mais cedo ou mais tarde, chegaremos a um nó cujo estado é 1. Neste caso, não é possível construir um grafo topológico ordenado.

Se o grafo não contém um ciclo, podemos construir um grafo topológico ordenado adicionando cada nó a uma lista quando o estado do nó se tornar 2. Essa lista na ordem inversa é um grafo topológico ordenado.

Page 8: CCO 101 PROCESSAMENTO DE DADOS

Exemplo 1Exemplo 1

No grafo do exemplo, a pesquisa primeiro procede do nó 1 ao nó 6:

1 3

4 5 6

1 3

4 5 6

Page 9: CCO 101 PROCESSAMENTO DE DADOS

Exemplo 1Exemplo 1

Agora o nó 6 foi processado, então ele é adicionado à lista. Depois disso, também nós 3, 2 e 1 são adicionados à lista

1 3

4 5 6

1 3

4 5 6

Page 10: CCO 101 PROCESSAMENTO DE DADOS

Exemplo 1Exemplo 1

Neste ponto, a lista é [6, 3, 2, 1]. A próxima pesquisa começa no nó 4:

1 3

4 5 6

1 3

4 5 6

Page 11: CCO 101 PROCESSAMENTO DE DADOS

Exemplo 1Exemplo 1

Assim, a lista final é [6, 3, 2, 1, 5, 4]. Nós processamos todos os nós, portanto, um tipo topológico foi encontrado. O tipo topológico é a lista inversa [4, 5, 1, 2, 3, 6]:

Observe que um tipo topológico não é único, e pode haver vários tipos topológicos para um gráfico.

1 34 5 6

Page 12: CCO 101 PROCESSAMENTO DE DADOS

Exemplo 2Exemplo 2

Consideremos agora um grafo para o qual não podemos construir um tipo topológico, porque o grafo contém um ciclo:

1 3

4 5 6

1 3

4 5 6

Page 13: CCO 101 PROCESSAMENTO DE DADOS

Exemplo 2Exemplo 2

A pesquisa prossegue da seguinte forma:

A pesquisa atinge o nó 2 cujo estado é 1, o que significa que o gráfico contém um ciclo. Neste exemplo, há um ciclo 2 → 3 → 5 → 2.

1 3

4 5 6

1 3

4 5 6

Page 16: CCO 101 PROCESSAMENTO DE DADOS

Programação DinâmicaProgramação Dinâmica

Se um grafo direcionado é acíclico, a programação dinâmica pode ser aplicada a ele. Por exemplo, podemos resolver de forma eficiente os seguintes problemas relacionados aos caminhos de um nó inicial para um nó final:

quantos caminhos diferentes existem?qual é o caminho mais curto / mais longo?qual é o número mínimo / máximo de arestas em um caminho?quais nós certamente aparecem em qualquer caminho?

Page 17: CCO 101 PROCESSAMENTO DE DADOS

Programação DinâmicaProgramação Dinâmica

Contando o número de caminhos

Como exemplo, vamos calcular o número de caminhos do nó 1 ao nó 6 no seguinte grafo:

1 3

4 5 6

1 3

4 5 6

Page 18: CCO 101 PROCESSAMENTO DE DADOS

Programação DinâmicaProgramação Dinâmica

Há três desses caminhos:

1 → 2 → 3 → 61 → 4 → 5 → 2 → 3 → 61 → 4 → 5 → 3 → 6

Deixe path(x) indicar o número de caminhos do nó 1 para o nó x. Como um caso base, path(1) = 1. Então, para calcular outros valores de path(x), podemos usar a recursão

path(x) = path(a1) + path(a

2) + … + path(a

k)

Page 19: CCO 101 PROCESSAMENTO DE DADOS

Programação DinâmicaProgramação Dinâmica

onde a1, a

2, … , a

k são os nós dos quais existe uma

direção de x. Uma vez que o grafo é acíclico, os valores dos path(x) podem ser calculados na ordem de um grafo topológico ordenado. Um grafo topológico ordenado para o grafo acima é o seguinte:

1 34 5 6

Page 21: CCO 101 PROCESSAMENTO DE DADOS

ExercícioExercício

● Monte um programa para determinar quais os caminhos a ser percorrido no grafo a seguir, saindo do nó 5. Primeiramente, com o caminhos preto, em seguida colocando os cinzas.

Page 22: CCO 101 PROCESSAMENTO DE DADOS

Programação DinâmicaProgramação Dinâmica

Portanto, o número de caminhos é o seguinte:

1 3

4 5 6

1 3

4 5 6

1 2 3

1 1 3

Page 23: CCO 101 PROCESSAMENTO DE DADOS

Programação DinâmicaProgramação Dinâmica

Por exemplo, para calcular o valor dos path(3), podemos usar da fórmula: path(2) + path(5), porque existem arestas dos nós 2 e 5 ao nó 3. Como os path(2) = 2 e path(5) = 1, concluímos que path(3) = 3.

Page 24: CCO 101 PROCESSAMENTO DE DADOS

2

Programação DinâmicaProgramação Dinâmica

Estendendo o algoritmo de DijkstraUm subproduto do algoritmo de Dijkstra é um grafo acíclico dirigido que indica para cada nó do grafo original as formas possíveis de alcançar o nó usando um caminho mais curto a partir do nó inicial. Por exemplo, no grafo:

1

3 4

5

3

5 2 4

8

1

Page 25: CCO 101 PROCESSAMENTO DE DADOS

2

Programação DinâmicaProgramação Dinâmica

Agora, podemos, por exemplo, calcular o número de caminhos mais curtos do nó 1 para o nó 5 usando a programação dinâmica:

1

3 4

5

3

5 2 4

1

Page 26: CCO 101 PROCESSAMENTO DE DADOS

2

Programação DinâmicaProgramação Dinâmica

Os caminhos mais curtos que o nó 1 pode usar para chegar ao nó 5, passa nas seguintes arestas:

1

3 4

5

3

5 2 4

1

1 1

2 3

3

Page 27: CCO 101 PROCESSAMENTO DE DADOS

Representando problemas como Representando problemas como grafosgrafos

Na verdade, qualquer problema de programação dinâmica pode ser representado como um grafo acíclico direcionado. Em tal grafo, cada nó corresponde a um estado de programação dinâmico e as arestas indicam como os estados dependem um do outro.Por exemplo, considere o problema de formar uma soma de dinheiro usando n moedas {c

1, c

2, …, c

k}.

Neste problema, podemos construir um grafo onde cada nó corresponde a uma soma de dinheiro e as arestas mostram como as moedas podem ser escolhidas.

Page 28: CCO 101 PROCESSAMENTO DE DADOS

Representando problemas como Representando problemas como grafosgrafos

Por exemplo, para moedas {1, 3, 4} e n = 6, o grafo é o seguinte:

Usando essa representação, o caminho mais curto do nó 0 para o nó n corresponde a uma solução com o número mínimo de moedas e o número total de caminhos do nó 0 para o nó n é igual ao número total de soluções.

3 51 2 60

Page 29: CCO 101 PROCESSAMENTO DE DADOS

Caminhos sucessoresCaminhos sucessores

Os grafos sucessores, o grau sucessor de cada nó é 1, isto é, exatamente uma borda começa em cada nó. Um grafo sucessor consiste em um ou mais componentes, cada um dos quais contém um ciclo e alguns caminhos que o levam.Os grafos sucessores às vezes são chamados de grafos funcionais. A razão para isso é que qualquer grafo sucessor corresponde a uma função que define as arestas do grafo. O parâmetro para a função é um nó do grafo, a função dá o sucessor desse nó.

Page 30: CCO 101 PROCESSAMENTO DE DADOS

Caminhos sucessoresCaminhos sucessores

Por exemplo, a função:

define o seguinte grafo:

x 1 2 3 4 5 6 7 8 9

succ(x) 3 5 7 6 2 2 1 6 3

9 3 1

7 6

2 5

4 8

Page 31: CCO 101 PROCESSAMENTO DE DADOS

ExercícioExercício

Monte um programa que dado o grafo a seguir, mostre a tabela do sucessor de cada um dos nós.

Page 32: CCO 101 PROCESSAMENTO DE DADOS

Caminhos sucessoresCaminhos sucessores

Uma vez que cada nó de um grafo sucessor possui um sucessor único, também podemos definir uma função succ(x,k) que dê o nó que alcançaremos se começarmos no nó x e caminhar avançar k vezes. Por exemplo, no grafo acima succ(4,6) = 2, porque alcançaremos o nó 2 caminhando 6 passos a partir do nó 4:

52 26 2 54

Page 33: CCO 101 PROCESSAMENTO DE DADOS

Caminhos sucessoresCaminhos sucessores

Uma maneira direta de calcular um valor de succ(x,k) é começar no nó x e caminhar k passos para a frente, o que leva O(k) tempo. No entanto, usando o pré-processamento, qualquer valor de succ(x,k) pode ser calculado apenas no tempo O(log k).A ideia é precalcular todos os valores de succ(x,k) onde k é uma potência de dois e, no máximo u, onde u é o número máximo de etapas que sempre vamos caminhar. Isso pode ser feito eficientemente, porque podemos usar a seguinte recursão:

Page 34: CCO 101 PROCESSAMENTO DE DADOS

Caminhos sucessoresCaminhos sucessores

Precalcular os valores leva o tempo O(n log u), porque os valores de O(log u) são calculados para cada nó. No grafo acima, os primeiros valores são os seguintes:

fsucc (x , k)={ fsucc(x) k=1fsucc( fsucc(x , k /2) , k /2) k>1

Page 35: CCO 101 PROCESSAMENTO DE DADOS

Caminhos sucessoresCaminhos sucessores

Depois disso, qualquer valor de succ(x,k) pode ser calculado apresentando o número de etapas k como uma soma de potência de dois. Por exemplo, se queremos calcular o valor de succ(x,11), primeiro formamos a representação 11 = 8 + 2 + 1. Usando isso,

x 1 2 3 4 5 6 7 8 9

succ(x,1) 3 5 7 6 2 2 1 6 3

succ(x,2) 7 2 1 2 5 5 3 2 7

succ(x,4) 3 2 7 2 5 5 1 2 3

succ(x,8) 7 2 1 2 5 5 3 2 7

Page 36: CCO 101 PROCESSAMENTO DE DADOS

Caminhos sucessoresCaminhos sucessores

succ(x, 11) = succ(succ(succ(x, 8), 2), 1)

Por exemplo, no grafo anterior

succ(4, 11) = succ(succ(succ(4, 8), 2), 1) == succ(succ(2, 2), 1) =

= succ(2, 1) = 5

Essa representação sempre consiste em partes de O(log k), portanto, calcular um valor de succ(x,k) leva tempo de O(log k).

Page 37: CCO 101 PROCESSAMENTO DE DADOS

ExercícioExercício

No exercício anterior, você montou um programa que construía a tabela dos valores sucessores de um grafo. Com a ideia do caminho sucessor, preencha a tabela a seguir.

Nó (x) Passo (p) succ(x, p)

S 4

T 7

Z 8

W 2

V 5

Page 38: CCO 101 PROCESSAMENTO DE DADOS

Detecção de cicloDetecção de ciclo

Considere um grafo sucessor que contém apenas um caminho que termina em um ciclo. Podemos fazer as seguintes perguntas: se iniciarmos nossa caminhada no nó de partida, qual é o primeiro nó no ciclo e quantos nós o ciclo contém?Por exemplo, no grafo

1 2 3 54

6

Page 39: CCO 101 PROCESSAMENTO DE DADOS

Detecção de cicloDetecção de ciclo

começamos nossa caminhada no nó 1, o primeiro nó que pertence ao ciclo é o nó 4 e o ciclo consiste em três nós (4, 5 e 6).

Uma maneira simples de detectar o ciclo é andar no grafo e acompanhar todos os nós que foram visitados. Uma vez que um nó é visitado pela segunda vez, podemos concluir que o nó é o primeiro nó no ciclo. Este método funciona no tempo O(n) e também usa a memória O(n).

Page 40: CCO 101 PROCESSAMENTO DE DADOS

Detecção de cicloDetecção de ciclo

No entanto, existem melhores algoritmos para detecção de ciclo. A complexidade do tempo de tais algoritmos ainda é O(n), mas eles apenas usam memória O(1). Esta é uma melhoria importante se n for grande. Em seguida, vamos discutir o algoritmo da Floyd que atinge essas propriedades.

Page 41: CCO 101 PROCESSAMENTO DE DADOS

ExercícioExercício

Faça um programa para determinar o ciclo do grafo a seguir. Se não houver, basta dizer que não tem.

Page 42: CCO 101 PROCESSAMENTO DE DADOS

Algoritmo de FloydAlgoritmo de Floyd

O algoritmo de Floyd avança no grafo usando dois ponteiros a e b. Ambos os ponteiros começam em um nó x que é o nó inicial do grafo. Então, em cada rodada, o ponteiro a percorre um passo em frente e o ponteiro b anda dois passos para a frente. O processo continua até que os ponteiros se encontrem:

a = succ(x);b = succ(succ(x));while (a != b) { a = succ(a); b = succ(succ(b));}

Page 43: CCO 101 PROCESSAMENTO DE DADOS

Algoritmo de FloydAlgoritmo de Floyd

Neste ponto, o ponteiro a andou k passos e o ponteiro b caminhou 2k etapas, então o comprimento do ciclo divide k. Assim, o primeiro nó que pertence ao ciclo pode ser encontrado movendo o ponteiro a para o nó x e avançando os ponteiros passo a passo até se encontrar novamente.

a = x;while (a != b) { a = succ(a); b = succ(b);}first = a;

Page 44: CCO 101 PROCESSAMENTO DE DADOS

Algoritmo de FloydAlgoritmo de Floyd

Depois disso, o comprimento do ciclo pode ser calculado da seguinte forma:

b = succ(a);length = 1;while (a != b) { b = succ(b); length++;}

Page 45: CCO 101 PROCESSAMENTO DE DADOS

ExercícioExercício

Utilizando o Algoritmo de Floyd, faça um programa para determinar o ciclo do grafo a seguir. Se não houver, basta dizer que não tem.

Page 46: CCO 101 PROCESSAMENTO DE DADOS

Sugestão para a provaSugestão para a prova

Guarde e estude esses programas.

Procure resolver os problemas do URI:1100, 1655 e 1738

Procure resolver os problemas do UVa186, 341, 423, 10793 e 534